2 * ngIRCd -- The Next Generation IRC Daemon
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 * Please read the file COPYING, README and AUTHORS for more information.
15 * Signal Handlers: Actions to be performed when the program
24 #include <sys/types.h>
35 #include "sighandlers.h"
37 static int signalpipe[2];
39 static const int signals_catch[] = {
40 SIGINT, SIGQUIT, SIGTERM, SIGHUP, SIGCHLD, SIGUSR1, SIGUSR2
49 Log(LOG_DEBUG, "--- Internal server state: %s ---",
50 Client_ID(Client_ThisServer()));
51 Log(LOG_DEBUG, "time()=%ld", time(NULL));
55 Log(LOG_DEBUG, "--- End of state dump ---");
64 #ifdef HAVE_SIGPROCMASK
70 sigprocmask(SIG_BLOCK, &set, NULL);
78 Signal_Unblock(int sig)
80 #ifdef HAVE_SIGPROCMASK
86 sigprocmask(SIG_UNBLOCK, &set, NULL);
88 int old = sigblock(0) & ~sig;
95 * Reload the server configuration file.
100 char old_name[CLIENT_ID_LEN];
101 unsigned old_nicklen;
103 Log( LOG_NOTICE|LOG_snotice, "Re-reading configuration NOW!" );
105 /* Remember old server name and nick name length */
106 strlcpy( old_name, Conf_ServerName, sizeof old_name );
107 old_nicklen = Conf_MaxNickLength;
109 /* Re-read configuration ... */
113 /* Close down all listening sockets */
114 Conn_ExitListeners( );
116 /* Recover old server name and nick name length: these values can't
117 * be changed during run-time */
118 if (strcmp(old_name, Conf_ServerName) != 0 ) {
119 strlcpy(Conf_ServerName, old_name, sizeof Conf_ServerName);
120 Log(LOG_ERR, "Can't change \"ServerName\" on runtime! Ignored new name.");
122 if (old_nicklen != Conf_MaxNickLength) {
123 Conf_MaxNickLength = old_nicklen;
124 Log(LOG_ERR, "Can't change \"MaxNickLength\" on runtime! Ignored new value.");
127 /* Create new pre-defined channels */
128 Channel_InitPredefined( );
130 if (!ConnSSL_InitLibrary())
131 Log(LOG_WARNING, "Re-Initializing SSL failed, using old keys");
133 /* Start listening on sockets */
134 Conn_InitListeners( );
136 /* Sync configuration with established connections */
137 Conn_SyncServerStruct( );
139 Log( LOG_NOTICE|LOG_snotice, "Re-reading of configuration done." );
144 * Signal handler of ngIRCd.
145 * This function is called whenever ngIRCd catches a signal sent by the
146 * user and/or the system to it. For example SIGTERM and SIGHUP.
148 * It blocks the signal and queues it for later execution by Signal_Handler_BH.
149 * @param Signal Number of the signal to handle.
152 Signal_Handler(int Signal)
158 /* shut down sever */
159 NGIRCd_SignalQuit = true;
162 /* child-process exited, avoid zombies */
163 while (waitpid( -1, NULL, WNOHANG) > 0)
168 if (! NGIRCd_Debug) {
169 Log(LOG_INFO|LOG_snotice,
170 "Got SIGUSR1, debug mode activated.");
172 strcpy(NGIRCd_DebugLevel, "2");
174 NGIRCd_Sniffer = true;
176 strcpy(NGIRCd_DebugLevel, "1");
180 Log(LOG_INFO|LOG_snotice,
181 "Got SIGUSR1, debug mode deactivated.");
182 strcpy(NGIRCd_DebugLevel, "");
183 NGIRCd_Debug = false;
185 NGIRCd_Sniffer = false;
193 * other signal: queue for later execution.
194 * This has the advantage that we are not restricted
195 * to functions that can be called safely from signal handlers.
197 if (write(signalpipe[1], &Signal, sizeof(Signal)) != -1)
198 Signal_Block(Signal);
199 } /* Signal_Handler */
203 * Signal processing handler of ngIRCd.
204 * This function is called from the main conn event loop in (io_dispatch)
205 * whenever ngIRCd has queued a signal.
207 * This function runs in normal context, not from the real signal handler,
208 * thus its not necessary to only use functions that are signal safe.
209 * @param Signal Number of the signal that was queued.
212 Signal_Handler_BH(int Signal)
216 /* re-read configuration */
225 Log(LOG_DEBUG, "Got signal %d! Ignored.", Signal);
228 Signal_Unblock(Signal);
233 Signal_Callback(int fd, short UNUSED what)
239 ret = (int)read(fd, &sig, sizeof(sig));
240 if (ret == sizeof(int))
241 Signal_Handler_BH(sig);
242 } while (ret == sizeof(int));
245 if (errno == EAGAIN || errno == EINTR)
248 Log(LOG_EMERG, "read from signal pipe: %s", strerror(errno));
252 Log(LOG_EMERG, "EOF on signal pipe");
258 * Initialize the signal handlers, catch
259 * those signals we are interested in and sets SIGPIPE to be ignored.
260 * @return true if initialization was sucessful.
266 #ifdef HAVE_SIGACTION
267 struct sigaction saction;
269 if (signalpipe[0] > 0 || signalpipe[1] > 0)
272 if (pipe(signalpipe))
275 if (!io_setnonblock(signalpipe[0]) ||
276 !io_setnonblock(signalpipe[1]))
278 if (!io_setcloexec(signalpipe[0]) ||
279 !io_setcloexec(signalpipe[1]))
281 #ifdef HAVE_SIGACTION
282 memset( &saction, 0, sizeof( saction ));
283 saction.sa_handler = Signal_Handler;
285 saction.sa_flags |= SA_RESTART;
288 saction.sa_flags |= SA_NOCLDWAIT;
291 for (i=0; i < C_ARRAY_SIZE(signals_catch) ; i++)
292 sigaction(signals_catch[i], &saction, NULL);
294 /* we handle write errors properly; ignore SIGPIPE */
295 saction.sa_handler = SIG_IGN;
296 sigaction(SIGPIPE, &saction, NULL);
298 for (i=0; i < C_ARRAY_SIZE(signals_catch) ; i++)
299 signal(signals_catch[i], Signal_Handler);
301 signal(SIGPIPE, SIG_IGN);
303 return io_event_create(signalpipe[0], IO_WANTREAD, Signal_Callback);
308 * Restores signals to their default behaviour.
310 * This should be called after a fork() in the new
311 * child prodcess, especially when we are about to call
312 * 3rd party code (e.g. PAM).
318 #ifdef HAVE_SIGACTION
319 struct sigaction saction;
321 memset(&saction, 0, sizeof(saction));
322 saction.sa_handler = SIG_DFL;
324 for (i=0; i < C_ARRAY_SIZE(signals_catch) ; i++)
325 sigaction(signals_catch[i], &saction, NULL);
326 sigaction(SIGPIPE, &saction, NULL);
328 for (i=0; i < C_ARRAY_SIZE(signals_catch) ; i++)
329 signal(signals_catch[i], SIG_DFL);
330 signal(SIGPIPE, SIG_DFL);
332 close(signalpipe[1]);
333 close(signalpipe[0]);