]> arthur.barton.de Git - ngircd-alex.git/blob - src/ngircd/sighandlers.c
remove NGIRCd_SignalRehash
[ngircd-alex.git] / src / ngircd / sighandlers.c
1 /*
2  * ngIRCd -- The Next Generation IRC Daemon
3  *
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.
9  */
10
11 #include "portab.h"
12
13 /**
14  * @file
15  * Signal Handlers: Actions to be performed when the program
16  * receives a signal.
17  */
18
19 #include <errno.h>
20 #include <unistd.h>
21 #include <stdlib.h>
22 #include <string.h>
23 #include <signal.h>
24 #include <sys/types.h>
25 #include <sys/wait.h>
26
27 #include "imp.h"
28 #include "conn.h"
29 #include "conf-ssl.h"
30 #include "channel.h"
31 #include "conf.h"
32 #include "io.h"
33 #include "log.h"
34 #include "ngircd.h"
35 #include "sighandlers.h"
36
37 static int signalpipe[2];
38
39 static void Signal_Block(int sig)
40 {
41 #ifdef HAVE_SIGPROCMASK
42         sigset_t set;
43
44         sigemptyset(&set);
45         sigaddset(&set, sig);
46
47         sigprocmask(SIG_BLOCK, &set, NULL);
48 #endif
49 }
50
51
52 static void Signal_Unblock(int sig)
53 {
54 #ifdef HAVE_SIGPROCMASK
55         sigset_t set;
56
57         sigemptyset(&set);
58         sigaddset(&set, sig);
59
60         sigprocmask(SIG_UNBLOCK, &set, NULL);
61 #endif
62 }
63
64 /**
65  * Reload the server configuration file.
66  */
67 static void
68 NGIRCd_Rehash( void )
69 {
70         char old_name[CLIENT_ID_LEN];
71         unsigned old_nicklen;
72
73         Log( LOG_NOTICE|LOG_snotice, "Re-reading configuration NOW!" );
74
75         /* Remember old server name and nick name length */
76         strlcpy( old_name, Conf_ServerName, sizeof old_name );
77         old_nicklen = Conf_MaxNickLength;
78
79         /* Re-read configuration ... */
80         if (!Conf_Rehash( ))
81                 return;
82
83         /* Close down all listening sockets */
84         Conn_ExitListeners( );
85
86         /* Recover old server name and nick name length: these values can't
87          * be changed during run-time */
88         if (strcmp(old_name, Conf_ServerName) != 0 ) {
89                 strlcpy(Conf_ServerName, old_name, sizeof Conf_ServerName);
90                 Log(LOG_ERR, "Can't change \"ServerName\" on runtime! Ignored new name.");
91         }
92         if (old_nicklen != Conf_MaxNickLength) {
93                 Conf_MaxNickLength = old_nicklen;
94                 Log(LOG_ERR, "Can't change \"MaxNickLength\" on runtime! Ignored new value.");
95         }
96
97         /* Create new pre-defined channels */
98         Channel_InitPredefined( );
99
100         if (!ConnSSL_InitLibrary())
101                 Log(LOG_WARNING, "Re-Initializing SSL failed, using old keys");
102
103         /* Start listening on sockets */
104         Conn_InitListeners( );
105
106         /* Sync configuration with established connections */
107         Conn_SyncServerStruct( );
108
109         Log( LOG_NOTICE|LOG_snotice, "Re-reading of configuration done." );
110 } /* NGIRCd_Rehash */
111
112
113
114 /**
115  * Signal handler of ngIRCd.
116  * This function is called whenever ngIRCd catches a signal sent by the
117  * user and/or the system to it. For example SIGTERM and SIGHUP.
118  *
119  * It blocks the signal and queues it for later execution by Signal_Handler_BH.
120  * @param Signal Number of the signal to handle.
121  */
122 static void Signal_Handler(int Signal)
123 {
124         switch (Signal) {
125         case SIGTERM:
126         case SIGINT:
127         case SIGQUIT:
128                 /* shut down sever */
129                 NGIRCd_SignalQuit = true;
130                 return;
131         case SIGHUP:
132                 break;
133         case SIGCHLD:
134                 /* child-process exited, avoid zombies */
135                 while (waitpid( -1, NULL, WNOHANG) > 0)
136                         ;
137                 return;
138         }
139
140         /*
141          * other signal: queue for later execution.
142          * This has the advantage that we are not restricted
143          * to functions that can be called safely from signal handlers.
144          */
145         if (write(signalpipe[1], &Signal, sizeof(Signal)) != -1)
146                 Signal_Block(Signal);
147 } /* Signal_Handler */
148
149
150 /**
151  * Signal processing handler of ngIRCd.
152  * This function is called from the main conn event loop in (io_dispatch)
153  * whenever ngIRCd has queued a signal.
154  *
155  * This function runs in normal context, not from the real signal handler,
156  * thus its not necessary to only use functions that are signal safe.
157  * @param Signal Number of the signal that was queued.
158  */
159 static void Signal_Handler_BH(int Signal)
160 {
161         switch (Signal) {
162         case SIGHUP:
163                 /* re-read configuration */
164                 NGIRCd_Rehash();
165                 break;
166 #ifdef DEBUG
167         default:
168                 Log(LOG_DEBUG, "Got signal %d! Ignored.", Signal);
169 #endif
170         }
171         Signal_Unblock(Signal);
172 }
173
174 static void Sig_callback(int fd, short UNUSED what)
175 {
176         int sig, ret;
177         (void) what;
178
179         do {
180                 ret = read(fd, &sig, sizeof(sig));
181                 if (ret == sizeof(int))
182                         Signal_Handler_BH(sig);
183         } while (ret == sizeof(int));
184
185         if (ret == -1) {
186                 if (errno == EAGAIN || errno == EINTR)
187                         return;
188
189                 Log(LOG_EMERG, "read from signal pipe: %s", strerror(errno));
190                 exit(1);
191         }
192
193         Log(LOG_EMERG, "EOF on signal pipe");
194         exit(1);
195 }
196
197
198 static const int signals_catch[] = { SIGINT, SIGQUIT, SIGTERM, SIGHUP, SIGCHLD, SIGUSR1, SIGUSR2 };
199 /**
200  * Initialize the signal handlers, catch
201  * those signals we are interested in and sets SIGPIPE to be ignored.
202  * @return true if initialization was sucessful.
203  */
204 bool Signals_Init(void)
205 {
206         size_t i;
207 #ifdef HAVE_SIGACTION
208         struct sigaction saction;
209 #endif
210
211         if (pipe(signalpipe))
212                 return false;
213
214         if (!io_setnonblock(signalpipe[0]) ||
215             !io_setnonblock(signalpipe[1]))
216                 return false;
217         if (!io_setcloexec(signalpipe[0]) ||
218             !io_setcloexec(signalpipe[1]))
219                 return false;
220 #ifdef HAVE_SIGACTION
221         memset( &saction, 0, sizeof( saction ));
222         saction.sa_handler = Signal_Handler;
223 #ifdef SA_RESTART
224         saction.sa_flags |= SA_RESTART;
225 #endif
226 #ifdef SA_NOCLDWAIT
227         saction.sa_flags |= SA_NOCLDWAIT;
228 #endif
229
230         for (i=0; i < C_ARRAY_SIZE(signals_catch) ; i++)
231                 sigaction(signals_catch[i], &saction, NULL);
232
233         /* we handle write errors properly; ignore SIGPIPE */
234         saction.sa_handler = SIG_IGN;
235         sigaction(SIGPIPE, &saction, NULL);
236 #else
237         for (i=0; i < C_ARRAY_SIZE(signals_catch) ; i++)
238                 signal(signals_catch[i], Signal_Handler);
239
240         signal(SIGPIPE, SIG_IGN);
241 #endif
242         return io_event_create(signalpipe[0], IO_WANTREAD,
243                                         Sig_callback);
244 } /* Initialize_Signal_Handler */
245
246
247 /**
248  * Restores signals to their default behaviour.
249  *
250  * This should be called after a fork() in the new
251  * child prodcess, especially when we are about to call
252  * 3rd party code (e.g. PAM).
253  */
254 void Signals_Exit(void)
255 {
256         size_t i;
257 #ifdef HAVE_SIGACTION
258         struct sigaction saction;
259
260         memset(&saction, 0, sizeof(saction));
261         saction.sa_handler = SIG_DFL;
262
263         for (i=0; i < C_ARRAY_SIZE(signals_catch) ; i++)
264                 sigaction(signals_catch[i], &saction, NULL);
265         sigaction(SIGPIPE, &saction, NULL);
266 #else
267         for (i=0; i < C_ARRAY_SIZE(signals_catch) ; i++)
268                 sigaction(signals_catch[i], &saction, NULL);
269         signal(SIGPIPE, SIG_DFL);
270 #endif
271         close(signalpipe[1]);
272         close(signalpipe[0]);
273 }
274
275 /* -eof- */