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>
31 #include "sighandlers.h"
33 static int signalpipe[2];
35 static void Signal_Block(int sig)
37 #ifdef HAVE_SIGPROCMASK
43 sigprocmask(SIG_BLOCK, &set, NULL);
48 static void Signal_Unblock(int sig)
50 #ifdef HAVE_SIGPROCMASK
56 sigprocmask(SIG_UNBLOCK, &set, NULL);
62 * Signal handler of ngIRCd.
63 * This function is called whenever ngIRCd catches a signal sent by the
64 * user and/or the system to it. For example SIGTERM and SIGHUP.
66 * It blocks the signal and queues it for later execution by Signal_Handler_BH.
67 * @param Signal Number of the signal to handle.
69 static void Signal_Handler(int Signal)
76 NGIRCd_SignalQuit = true;
79 /* re-read configuration */
80 NGIRCd_SignalRehash = true;
83 /* child-process exited, avoid zombies */
84 while (waitpid( -1, NULL, WNOHANG) > 0)
90 * other signal: queue for later execution.
91 * This has the advantage that we are not restricted
92 * to functions that can be called safely from signal handlers.
94 if (write(signalpipe[1], &Signal, sizeof(Signal)) != -1)
96 } /* Signal_Handler */
100 * Signal processing handler of ngIRCd.
101 * This function is called from the main conn event loop in (io_dispatch)
102 * whenever ngIRCd has queued a signal.
104 * This function runs in normal context, not from the real signal handler,
105 * thus its not necessary to only use functions that are signal safe.
106 * @param Signal Number of the signal that was queued.
108 static void Signal_Handler_BH(int Signal)
113 Log(LOG_DEBUG, "Got signal %d! Ignored.", Signal);
116 Signal_Unblock(Signal);
119 static void Sig_callback(int fd, short UNUSED what)
125 ret = read(fd, &sig, sizeof(sig));
126 if (ret == sizeof(int))
127 Signal_Handler_BH(sig);
128 } while (ret == sizeof(int));
131 if (errno == EAGAIN || errno == EINTR)
134 Log(LOG_EMERG, "read from signal pipe: %s", strerror(errno));
138 Log(LOG_EMERG, "EOF on signal pipe");
143 static const int signals_catch[] = { SIGINT, SIGQUIT, SIGTERM, SIGHUP, SIGCHLD, SIGUSR1, SIGUSR2 };
145 * Initialize the signal handlers, catch
146 * those signals we are interested in and sets SIGPIPE to be ignored.
147 * @return true if initialization was sucessful.
149 bool Signals_Init(void)
152 #ifdef HAVE_SIGACTION
153 struct sigaction saction;
156 if (pipe(signalpipe))
159 if (!io_setnonblock(signalpipe[0]) ||
160 !io_setnonblock(signalpipe[1]))
162 if (!io_setcloexec(signalpipe[0]) ||
163 !io_setcloexec(signalpipe[1]))
165 #ifdef HAVE_SIGACTION
166 memset( &saction, 0, sizeof( saction ));
167 saction.sa_handler = Signal_Handler;
169 saction.sa_flags |= SA_RESTART;
172 saction.sa_flags |= SA_NOCLDWAIT;
175 for (i=0; i < C_ARRAY_SIZE(signals_catch) ; i++)
176 sigaction(signals_catch[i], &saction, NULL);
178 /* we handle write errors properly; ignore SIGPIPE */
179 saction.sa_handler = SIG_IGN;
180 sigaction(SIGPIPE, &saction, NULL);
182 for (i=0; i < C_ARRAY_SIZE(signals_catch) ; i++)
183 signal(signals_catch[i], Signal_Handler);
185 signal(SIGPIPE, SIG_IGN);
187 return io_event_create(signalpipe[0], IO_WANTREAD,
189 } /* Initialize_Signal_Handler */
193 * Restores signals to their default behaviour.
195 * This should be called after a fork() in the new
196 * child prodcess, especially when we are about to call
197 * 3rd party code (e.g. PAM).
199 void Signals_Exit(void)
202 #ifdef HAVE_SIGACTION
203 struct sigaction saction;
205 memset(&saction, 0, sizeof(saction));
206 saction.sa_handler = SIG_DFL;
208 for (i=0; i < C_ARRAY_SIZE(signals_catch) ; i++)
209 sigaction(signals_catch[i], &saction, NULL);
210 sigaction(SIGPIPE, &saction, NULL);
212 for (i=0; i < C_ARRAY_SIZE(signals_catch) ; i++)
213 sigaction(signals_catch[i], &saction, NULL);
214 signal(SIGPIPE, SIG_DFL);
216 close(signalpipe[1]);
217 close(signalpipe[0]);