2 * ngIRCd -- The Next Generation IRC Daemon
3 * Copyright (c)2001-2015 Alexander Barton (alex@barton.de) and Contributors.
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 * Please read the file COPYING, README and AUTHORS for more information.
16 * Signal Handlers: Actions to be performed when the program
25 #include <sys/types.h>
36 #include "sighandlers.h"
38 static int signalpipe[2];
40 static const int signals_catch[] = {
41 SIGINT, SIGQUIT, SIGTERM, SIGHUP, SIGCHLD, SIGUSR1, SIGUSR2
49 Log(LOG_DEBUG, "--- Internal server state: %s ---",
50 Client_ID(Client_ThisServer()));
52 Log(LOG_DEBUG, "time()=%llu", (unsigned long long)time(NULL));
54 Log(LOG_DEBUG, "time()=%lu", (unsigned long)time(NULL));
59 Log(LOG_DEBUG, "--- End of state dump ---");
67 #ifdef HAVE_SIGPROCMASK
73 sigprocmask(SIG_BLOCK, &set, NULL);
80 Signal_Unblock(int sig)
82 #ifdef HAVE_SIGPROCMASK
88 sigprocmask(SIG_UNBLOCK, &set, NULL);
90 int old = sigblock(0) & ~sig;
96 * Reload the server configuration file.
101 char old_name[CLIENT_ID_LEN];
102 unsigned old_nicklen;
104 Log( LOG_NOTICE|LOG_snotice, "Re-reading configuration NOW!" );
106 /* Remember old server name and nickname length */
107 strlcpy( old_name, Conf_ServerName, sizeof old_name );
108 old_nicklen = Conf_MaxNickLength;
110 /* Re-read configuration ... */
114 /* Close down all listening sockets */
115 Conn_ExitListeners( );
117 /* Recover old server name and nickname length: these values can't
118 * be changed during run-time */
119 if (strcmp(old_name, Conf_ServerName) != 0 ) {
120 strlcpy(Conf_ServerName, old_name, sizeof Conf_ServerName);
122 "Can't change server name (\"Name\") on runtime! Ignored new name.");
124 if (old_nicklen != Conf_MaxNickLength) {
125 Conf_MaxNickLength = old_nicklen;
127 "Can't change \"MaxNickLength\" on runtime! Ignored new value.");
130 /* Create new pre-defined channels */
131 Channel_InitPredefined( );
133 if (!ConnSSL_InitLibrary())
135 "Re-Initializing of SSL failed!");
137 /* Start listening on sockets */
138 Conn_InitListeners( );
140 /* Sync configuration with established connections */
141 Conn_SyncServerStruct( );
143 Log( LOG_NOTICE|LOG_snotice, "Re-reading of configuration done." );
147 * Signal handler of ngIRCd.
148 * This function is called whenever ngIRCd catches a signal sent by the
149 * user and/or the system to it. For example SIGTERM and SIGHUP.
151 * It blocks the signal and queues it for later execution by Signal_Handler_BH.
152 * @param Signal Number of the signal to handle.
155 Signal_Handler(int Signal)
157 if (Signal != SIGCHLD) {
158 #ifdef HAVE_STRSIGNAL
159 Log(LOG_INFO, "Got signal \"%s\" ...", strsignal(Signal));
161 Log(LOG_INFO, "Got signal %d ...", Signal);
169 /* shut down sever */
170 NGIRCd_SignalQuit = true;
173 /* child-process exited, avoid zombies */
174 while (waitpid( -1, NULL, WNOHANG) > 0)
179 if (! NGIRCd_Debug) {
180 Log(LOG_INFO|LOG_snotice,
181 "Got SIGUSR1, debug mode activated.");
183 strcpy(NGIRCd_DebugLevel, "2");
185 NGIRCd_Sniffer = true;
187 strcpy(NGIRCd_DebugLevel, "1");
191 Log(LOG_INFO|LOG_snotice,
192 "Got SIGUSR1, debug mode deactivated.");
193 strcpy(NGIRCd_DebugLevel, "");
194 NGIRCd_Debug = false;
196 NGIRCd_Sniffer = false;
204 * other signal: queue for later execution.
205 * This has the advantage that we are not restricted
206 * to functions that can be called safely from signal handlers.
208 if (write(signalpipe[1], &Signal, sizeof(Signal)) != -1)
209 Signal_Block(Signal);
210 } /* Signal_Handler */
213 * Signal processing handler of ngIRCd.
214 * This function is called from the main conn event loop in (io_dispatch)
215 * whenever ngIRCd has queued a signal.
217 * This function runs in normal context, not from the real signal handler,
218 * thus its not necessary to only use functions that are signal safe.
219 * @param Signal Number of the signal that was queued.
222 Signal_Handler_BH(int Signal)
226 /* re-read configuration */
232 Log(LOG_INFO|LOG_snotice,
233 "Got SIGUSR2, dumping internal state ...");
238 Log(LOG_DEBUG, "Got signal %d! Ignored.", Signal);
241 Signal_Unblock(Signal);
245 Signal_Callback(int fd, short UNUSED what)
251 ret = (int)read(fd, &sig, sizeof(sig));
252 if (ret == sizeof(int))
253 Signal_Handler_BH(sig);
254 } while (ret == sizeof(int));
257 if (errno == EAGAIN || errno == EINTR)
260 Log(LOG_EMERG, "Read from signal pipe: %s - Exiting!",
265 Log(LOG_EMERG, "EOF on signal pipe!? - Exiting!");
270 * Initialize the signal handlers, catch
271 * those signals we are interested in and sets SIGPIPE to be ignored.
272 * @return true if initialization was successful.
278 #ifdef HAVE_SIGACTION
279 struct sigaction saction;
281 if (signalpipe[0] > 0 || signalpipe[1] > 0)
284 if (pipe(signalpipe))
287 if (!io_setnonblock(signalpipe[0]) ||
288 !io_setnonblock(signalpipe[1]))
290 if (!io_setcloexec(signalpipe[0]) ||
291 !io_setcloexec(signalpipe[1]))
293 #ifdef HAVE_SIGACTION
294 memset( &saction, 0, sizeof( saction ));
295 saction.sa_handler = Signal_Handler;
297 saction.sa_flags |= SA_RESTART;
300 saction.sa_flags |= SA_NOCLDWAIT;
303 for (i=0; i < C_ARRAY_SIZE(signals_catch) ; i++)
304 sigaction(signals_catch[i], &saction, NULL);
306 /* we handle write errors properly; ignore SIGPIPE */
307 saction.sa_handler = SIG_IGN;
308 sigaction(SIGPIPE, &saction, NULL);
310 for (i=0; i < C_ARRAY_SIZE(signals_catch) ; i++)
311 signal(signals_catch[i], Signal_Handler);
313 signal(SIGPIPE, SIG_IGN);
315 return io_event_create(signalpipe[0], IO_WANTREAD, Signal_Callback);
319 * Restores signals to their default behavior.
321 * This should be called after a fork() in the new
322 * child prodcess, especially when we are about to call
323 * 3rd party code (e.g. PAM).
329 #ifdef HAVE_SIGACTION
330 struct sigaction saction;
332 memset(&saction, 0, sizeof(saction));
333 saction.sa_handler = SIG_DFL;
335 for (i=0; i < C_ARRAY_SIZE(signals_catch) ; i++)
336 sigaction(signals_catch[i], &saction, NULL);
337 sigaction(SIGPIPE, &saction, NULL);
339 for (i=0; i < C_ARRAY_SIZE(signals_catch) ; i++)
340 signal(signals_catch[i], SIG_DFL);
341 signal(SIGPIPE, SIG_DFL);
343 close(signalpipe[1]);
344 close(signalpipe[0]);
345 signalpipe[0] = signalpipe[1] = 0;