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 void Signal_Block(int sig)
41 #ifdef HAVE_SIGPROCMASK
47 sigprocmask(SIG_BLOCK, &set, NULL);
54 static void Signal_Unblock(int sig)
56 #ifdef HAVE_SIGPROCMASK
62 sigprocmask(SIG_UNBLOCK, &set, NULL);
64 int old = sigblock(0) & ~sig;
70 * Reload the server configuration file.
75 char old_name[CLIENT_ID_LEN];
78 Log( LOG_NOTICE|LOG_snotice, "Re-reading configuration NOW!" );
80 /* Remember old server name and nick name length */
81 strlcpy( old_name, Conf_ServerName, sizeof old_name );
82 old_nicklen = Conf_MaxNickLength;
84 /* Re-read configuration ... */
88 /* Close down all listening sockets */
89 Conn_ExitListeners( );
91 /* Recover old server name and nick name length: these values can't
92 * be changed during run-time */
93 if (strcmp(old_name, Conf_ServerName) != 0 ) {
94 strlcpy(Conf_ServerName, old_name, sizeof Conf_ServerName);
95 Log(LOG_ERR, "Can't change \"ServerName\" on runtime! Ignored new name.");
97 if (old_nicklen != Conf_MaxNickLength) {
98 Conf_MaxNickLength = old_nicklen;
99 Log(LOG_ERR, "Can't change \"MaxNickLength\" on runtime! Ignored new value.");
102 /* Create new pre-defined channels */
103 Channel_InitPredefined( );
105 if (!ConnSSL_InitLibrary())
106 Log(LOG_WARNING, "Re-Initializing SSL failed, using old keys");
108 /* Start listening on sockets */
109 Conn_InitListeners( );
111 /* Sync configuration with established connections */
112 Conn_SyncServerStruct( );
114 Log( LOG_NOTICE|LOG_snotice, "Re-reading of configuration done." );
115 } /* NGIRCd_Rehash */
120 * Signal handler of ngIRCd.
121 * This function is called whenever ngIRCd catches a signal sent by the
122 * user and/or the system to it. For example SIGTERM and SIGHUP.
124 * It blocks the signal and queues it for later execution by Signal_Handler_BH.
125 * @param Signal Number of the signal to handle.
127 static void Signal_Handler(int Signal)
133 /* shut down sever */
134 NGIRCd_SignalQuit = true;
139 /* child-process exited, avoid zombies */
140 while (waitpid( -1, NULL, WNOHANG) > 0)
146 * other signal: queue for later execution.
147 * This has the advantage that we are not restricted
148 * to functions that can be called safely from signal handlers.
150 if (write(signalpipe[1], &Signal, sizeof(Signal)) != -1)
151 Signal_Block(Signal);
152 } /* Signal_Handler */
156 * Signal processing handler of ngIRCd.
157 * This function is called from the main conn event loop in (io_dispatch)
158 * whenever ngIRCd has queued a signal.
160 * This function runs in normal context, not from the real signal handler,
161 * thus its not necessary to only use functions that are signal safe.
162 * @param Signal Number of the signal that was queued.
164 static void Signal_Handler_BH(int Signal)
168 /* re-read configuration */
173 Log(LOG_DEBUG, "Got signal %d! Ignored.", Signal);
176 Signal_Unblock(Signal);
179 static void Sig_callback(int fd, short UNUSED what)
185 ret = read(fd, &sig, sizeof(sig));
186 if (ret == sizeof(int))
187 Signal_Handler_BH(sig);
188 } while (ret == sizeof(int));
191 if (errno == EAGAIN || errno == EINTR)
194 Log(LOG_EMERG, "read from signal pipe: %s", strerror(errno));
198 Log(LOG_EMERG, "EOF on signal pipe");
203 static const int signals_catch[] = { SIGINT, SIGQUIT, SIGTERM, SIGHUP, SIGCHLD, SIGUSR1, SIGUSR2 };
205 * Initialize the signal handlers, catch
206 * those signals we are interested in and sets SIGPIPE to be ignored.
207 * @return true if initialization was sucessful.
209 bool Signals_Init(void)
212 #ifdef HAVE_SIGACTION
213 struct sigaction saction;
216 if (pipe(signalpipe))
219 if (!io_setnonblock(signalpipe[0]) ||
220 !io_setnonblock(signalpipe[1]))
222 if (!io_setcloexec(signalpipe[0]) ||
223 !io_setcloexec(signalpipe[1]))
225 #ifdef HAVE_SIGACTION
226 memset( &saction, 0, sizeof( saction ));
227 saction.sa_handler = Signal_Handler;
229 saction.sa_flags |= SA_RESTART;
232 saction.sa_flags |= SA_NOCLDWAIT;
235 for (i=0; i < C_ARRAY_SIZE(signals_catch) ; i++)
236 sigaction(signals_catch[i], &saction, NULL);
238 /* we handle write errors properly; ignore SIGPIPE */
239 saction.sa_handler = SIG_IGN;
240 sigaction(SIGPIPE, &saction, NULL);
242 for (i=0; i < C_ARRAY_SIZE(signals_catch) ; i++)
243 signal(signals_catch[i], Signal_Handler);
245 signal(SIGPIPE, SIG_IGN);
247 return io_event_create(signalpipe[0], IO_WANTREAD,
249 } /* Initialize_Signal_Handler */
253 * Restores signals to their default behaviour.
255 * This should be called after a fork() in the new
256 * child prodcess, especially when we are about to call
257 * 3rd party code (e.g. PAM).
259 void Signals_Exit(void)
262 #ifdef HAVE_SIGACTION
263 struct sigaction saction;
265 memset(&saction, 0, sizeof(saction));
266 saction.sa_handler = SIG_DFL;
268 for (i=0; i < C_ARRAY_SIZE(signals_catch) ; i++)
269 sigaction(signals_catch[i], &saction, NULL);
270 sigaction(SIGPIPE, &saction, NULL);
272 for (i=0; i < C_ARRAY_SIZE(signals_catch) ; i++)
273 sigaction(signals_catch[i], &saction, NULL);
274 signal(SIGPIPE, SIG_DFL);
276 close(signalpipe[1]);
277 close(signalpipe[0]);