mirror of
https://github.com/anope/anope.git
synced 2026-07-06 14:13:13 +02:00
Rewrote the signal handling to use sigaction
This commit is contained in:
@@ -115,7 +115,6 @@ E bool protocoldebug;
|
||||
E bool quitting;
|
||||
E bool restarting;
|
||||
E Anope::string quitmsg;
|
||||
E bool save_data;
|
||||
E time_t start_time;
|
||||
|
||||
E ConnectionSocket *UplinkSock;
|
||||
|
||||
+1
-7
@@ -572,12 +572,6 @@ class CoreExport Module : public Extensible
|
||||
*/
|
||||
virtual void OnShutdown() { }
|
||||
|
||||
/** Called on signal
|
||||
* @param signum The signum
|
||||
* @param msg The quitmsg
|
||||
*/
|
||||
virtual void OnSignal(int signum, const Anope::string &msg) { }
|
||||
|
||||
/** Called before a nick expires
|
||||
* @param na The nick
|
||||
* @return EVENT_CONTINUE to let other modules decide, EVENT_STOP to halt the command and not process it
|
||||
@@ -1077,7 +1071,7 @@ enum Implementation
|
||||
|
||||
/* Other */
|
||||
I_OnReload, I_OnNewServer, I_OnPreServerConnect, I_OnServerConnect, I_OnPreUplinkSync, I_OnServerDisconnect, I_OnPreCommandRun,
|
||||
I_OnPreCommand, I_OnPostCommand, I_OnRestart, I_OnShutdown, I_OnSignal,
|
||||
I_OnPreCommand, I_OnPostCommand, I_OnRestart, I_OnShutdown,
|
||||
I_OnServerQuit, I_OnTopicUpdated,
|
||||
I_OnEncrypt, I_OnDecrypt,
|
||||
I_OnChannelModeSet, I_OnChannelModeUnset, I_OnUserModeSet, I_OnUserModeUnset, I_OnChannelModeAdd, I_OnUserModeAdd,
|
||||
|
||||
@@ -241,6 +241,23 @@ class DatabaseException : public CoreException
|
||||
virtual ~DatabaseException() throw() { }
|
||||
};
|
||||
|
||||
class Signal
|
||||
{
|
||||
static std::vector<Signal *> SignalHandlers;
|
||||
static void SignalHandler(int signal);
|
||||
|
||||
struct sigaction action;
|
||||
sig_atomic_t called;
|
||||
public:
|
||||
static void Process();
|
||||
|
||||
int signal;
|
||||
|
||||
Signal(int s);
|
||||
~Signal();
|
||||
virtual void OnSignal() = 0;
|
||||
};
|
||||
|
||||
/** Debug cast to be used instead of dynamic_cast, this uses dynamic_cast
|
||||
* for debug builds and static_cast on releass builds to speed up the program
|
||||
* because dynamic_cast relies on RTTI.
|
||||
|
||||
+3
-3
@@ -254,7 +254,7 @@ class CoreExport BufferedSocket : public Socket
|
||||
/* Part of a message sent from the server, but not totally received */
|
||||
Anope::string extrabuf;
|
||||
/* How much data was received from this socket */
|
||||
size_t RecvLen;
|
||||
int RecvLen;
|
||||
|
||||
public:
|
||||
/** Blank constructor
|
||||
@@ -297,12 +297,12 @@ class CoreExport BufferedSocket : public Socket
|
||||
/** Get the length of the read buffer
|
||||
* @return The length of the read buffer
|
||||
*/
|
||||
size_t ReadBufferLen() const;
|
||||
int ReadBufferLen() const;
|
||||
|
||||
/** Get the length of the write buffer
|
||||
* @return The length of the write buffer
|
||||
*/
|
||||
size_t WriteBufferLen() const;
|
||||
int WriteBufferLen() const;
|
||||
};
|
||||
|
||||
class CoreExport ListenSocket : public Socket
|
||||
|
||||
@@ -26,7 +26,8 @@ class CommandOSRestart : public Command
|
||||
{
|
||||
User *u = source.u;
|
||||
quitmsg = "RESTART command received from " + u->nick;
|
||||
quitting = save_data = restarting = true;
|
||||
save_databases();
|
||||
quitting = restarting = true;
|
||||
return MOD_CONT;
|
||||
}
|
||||
|
||||
|
||||
@@ -26,7 +26,8 @@ class CommandOSShutdown : public Command
|
||||
{
|
||||
User *u = source.u;
|
||||
quitmsg = "SHUTDOWN command received from " + u->nick;
|
||||
quitting = save_data = true;
|
||||
save_databases();
|
||||
quitting = true;
|
||||
return MOD_CONT;
|
||||
}
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@ class CommandOSUpdate : public Command
|
||||
CommandReturn Execute(CommandSource &source, const std::vector<Anope::string> ¶ms)
|
||||
{
|
||||
source.Reply(_("Updating databases."));
|
||||
save_data = true;
|
||||
save_databases();
|
||||
return MOD_CONT;
|
||||
}
|
||||
|
||||
|
||||
+48
-8
@@ -209,6 +209,52 @@ static void write_pidfile()
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
class SignalReload : public Signal
|
||||
{
|
||||
public:
|
||||
SignalReload(int sig) : Signal(sig) { }
|
||||
|
||||
void OnSignal()
|
||||
{
|
||||
Log() << "Received SIGHUP: Saving databases & rehashing configuration";
|
||||
|
||||
save_databases();
|
||||
|
||||
ServerConfig *old_config = Config;
|
||||
try
|
||||
{
|
||||
Config = new ServerConfig();
|
||||
FOREACH_MOD(I_OnReload, OnReload());
|
||||
delete old_config;
|
||||
}
|
||||
catch (const ConfigException &ex)
|
||||
{
|
||||
Config = old_config;
|
||||
Log() << "Error reloading configuration file: " << ex.GetReason();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
class SignalExit : public Signal
|
||||
{
|
||||
public:
|
||||
SignalExit(int sig) : Signal(sig) { }
|
||||
|
||||
void OnSignal()
|
||||
{
|
||||
#ifndef _WIN32
|
||||
Log() << "Received " << strsignal(this->signal) << " signal (" << this->signal << "), exiting.";
|
||||
quitmsg = Anope::string("Services terminating via signal ") + strsignal(this->signal) + " (" + stringify(this->signal) + ")";
|
||||
#else
|
||||
Log() << "Received signal " << this->signal << ", exiting.";
|
||||
quitmsg = Anope::string("Services terminating via signal ") + stringify(this->signal);
|
||||
#endif
|
||||
|
||||
save_databases();
|
||||
quitting = true;
|
||||
}
|
||||
};
|
||||
|
||||
void Init(int ac, char **av)
|
||||
{
|
||||
int started_from_term = isatty(0) && isatty(1) && isatty(2);
|
||||
@@ -377,14 +423,8 @@ void Init(int ac, char **av)
|
||||
/* Announce ourselves to the logfile. */
|
||||
Log() << "Anope " << Anope::Version() << " starting up" << (debug || readonly ? " (options:" : "") << (debug ? " debug" : "") << (readonly ? " readonly" : "") << (debug || readonly ? ")" : "");
|
||||
|
||||
/* Set signal handlers. Catch certain signals to let us do things or
|
||||
* panic as necessary, and ignore all others.
|
||||
*/
|
||||
#ifndef _WIN32
|
||||
signal(SIGHUP, sighandler);
|
||||
#endif
|
||||
signal(SIGTERM, sighandler);
|
||||
signal(SIGINT, sighandler);
|
||||
static SignalReload sig_hup(SIGHUP);
|
||||
static SignalExit sig_term(SIGTERM), sig_int(SIGINT);
|
||||
|
||||
/* Initialize multi-language support */
|
||||
Log(LOG_DEBUG) << "Loading Languages...";
|
||||
|
||||
+40
-68
@@ -61,9 +61,6 @@ bool restarting = false;
|
||||
/* Contains a message as to why services is terminating */
|
||||
Anope::string quitmsg;
|
||||
|
||||
/* Should we update the databases now? */
|
||||
bool save_data = false;
|
||||
|
||||
/* At what time were we started? */
|
||||
time_t start_time = time(NULL);
|
||||
|
||||
@@ -83,8 +80,7 @@ class UpdateTimer : public Timer
|
||||
|
||||
void Tick(time_t)
|
||||
{
|
||||
if (!readonly)
|
||||
save_databases();
|
||||
save_databases();
|
||||
}
|
||||
};
|
||||
|
||||
@@ -212,66 +208,45 @@ void save_databases()
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
/* If we get a weird signal, come here. */
|
||||
std::vector<Signal *> Signal::SignalHandlers;
|
||||
|
||||
void sighandler(int signum)
|
||||
void Signal::SignalHandler(int signal)
|
||||
{
|
||||
if (quitmsg.empty())
|
||||
#ifndef _WIN32
|
||||
quitmsg = Anope::string("Services terminating via signal ") + strsignal(signum) + " (" + stringify(signum) + ")";
|
||||
#else
|
||||
quitmsg = Anope::string("Services terminating via signal ") + stringify(signum);
|
||||
#endif
|
||||
|
||||
if (started)
|
||||
{
|
||||
switch (signum)
|
||||
{
|
||||
#ifndef _WIN32
|
||||
case SIGHUP:
|
||||
{
|
||||
Log() << "Received SIGHUP: Saving databases & rehashing configuration";
|
||||
|
||||
save_databases();
|
||||
|
||||
ServerConfig *old_config = Config;
|
||||
try
|
||||
{
|
||||
Config = new ServerConfig();
|
||||
FOREACH_MOD(I_OnReload, OnReload());
|
||||
delete old_config;
|
||||
}
|
||||
catch (const ConfigException &ex)
|
||||
{
|
||||
Config = old_config;
|
||||
Log() << "Error reloading configuration file: " << ex.GetReason();
|
||||
}
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
case SIGINT:
|
||||
case SIGTERM:
|
||||
signal(signum, SIG_IGN);
|
||||
#ifndef _WIN32
|
||||
signal(SIGHUP, SIG_IGN);
|
||||
#endif
|
||||
|
||||
#ifndef _WIN32
|
||||
Log() << "Received " << strsignal(signum) << " signal (" << signum << "), exiting.";
|
||||
#else
|
||||
Log() << "Received signal " << signum << ", exiting.";
|
||||
#endif
|
||||
|
||||
save_databases();
|
||||
quitting = true;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
FOREACH_MOD(I_OnSignal, OnSignal(signum, quitmsg));
|
||||
for (unsigned i = 0, j = SignalHandlers.size(); i < j; ++i)
|
||||
if (SignalHandlers[i]->signal == signal)
|
||||
SignalHandlers[i]->called = true;
|
||||
}
|
||||
|
||||
void Signal::Process()
|
||||
{
|
||||
for (unsigned i = 0, j = SignalHandlers.size(); i < j; ++i)
|
||||
if (SignalHandlers[i]->called == true)
|
||||
{
|
||||
Signal *s = SignalHandlers[i];
|
||||
s->called = false;
|
||||
s->OnSignal();
|
||||
}
|
||||
}
|
||||
|
||||
Signal::Signal(int s) : called(false), signal(s)
|
||||
{
|
||||
this->action.sa_flags = 0;
|
||||
sigemptyset(&this->action.sa_mask);
|
||||
this->action.sa_handler = SignalHandler;
|
||||
|
||||
sigaction(s, &this->action, NULL);
|
||||
|
||||
SignalHandlers.push_back(this);
|
||||
}
|
||||
|
||||
Signal::~Signal()
|
||||
{
|
||||
std::vector<Signal *>::iterator it = std::find(SignalHandlers.begin(), SignalHandlers.end(), this);
|
||||
if (it != SignalHandlers.end())
|
||||
SignalHandlers.erase(it);
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
/** The following comes from InspIRCd to get the full path of the Anope executable
|
||||
@@ -388,6 +363,10 @@ int main(int ac, char **av, char **envp)
|
||||
{
|
||||
Log(LOG_DEBUG_2) << "Top of main loop";
|
||||
|
||||
/* Process signals */
|
||||
Signal::Process();
|
||||
|
||||
/* Process timers */
|
||||
if (Anope::CurTime - last_check >= Config->TimeoutCheck)
|
||||
{
|
||||
TimerManager::TickTimers(Anope::CurTime);
|
||||
@@ -405,13 +384,6 @@ int main(int ac, char **av, char **envp)
|
||||
SocketEngine::Process();
|
||||
}
|
||||
|
||||
if (save_data)
|
||||
{
|
||||
ircdproto->SendGlobops(NULL, "Updating databases on shutdown, please wait.");
|
||||
save_databases();
|
||||
save_data = false;
|
||||
}
|
||||
|
||||
if (restarting)
|
||||
{
|
||||
FOREACH_MOD(I_OnRestart, OnRestart());
|
||||
|
||||
+9
-5
@@ -467,11 +467,15 @@ bool BufferedSocket::ProcessRead()
|
||||
{
|
||||
char tbuffer[NET_BUFSIZE] = "";
|
||||
|
||||
RecvLen = this->IO->Recv(this, tbuffer, sizeof(tbuffer) - 1);
|
||||
if (RecvLen == -2)
|
||||
this->RecvLen = 0;
|
||||
|
||||
int len = this->IO->Recv(this, tbuffer, sizeof(tbuffer) - 1);
|
||||
if (len == -2)
|
||||
return true;
|
||||
else if (RecvLen <= 0)
|
||||
else if (len <= 0)
|
||||
return false;
|
||||
|
||||
this->RecvLen = len;
|
||||
|
||||
Anope::string sbuffer = this->extrabuf;
|
||||
sbuffer += tbuffer;
|
||||
@@ -559,7 +563,7 @@ void BufferedSocket::Write(const Anope::string &message)
|
||||
/** Get the length of the read buffer
|
||||
* @return The length of the read buffer
|
||||
*/
|
||||
size_t BufferedSocket::ReadBufferLen() const
|
||||
int BufferedSocket::ReadBufferLen() const
|
||||
{
|
||||
return RecvLen;
|
||||
}
|
||||
@@ -567,7 +571,7 @@ size_t BufferedSocket::ReadBufferLen() const
|
||||
/** Get the length of the write buffer
|
||||
* @return The length of the write buffer
|
||||
*/
|
||||
size_t BufferedSocket::WriteBufferLen() const
|
||||
int BufferedSocket::WriteBufferLen() const
|
||||
{
|
||||
return this->WriteBuffer.length();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user