ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/hybrid-ircservices-1/signals.c
Revision: 1209
Committed: Thu Aug 25 19:05:49 2011 UTC (14 years, 11 months ago) by michael
Content type: text/x-csrc
File size: 6377 byte(s)
Log Message:
- run everything thru indent
  "-bli0 -di1 -npcs -nut -cdw -bls -nbbo -bap"

File Contents

# Content
1 /* Signal handling routines.
2 *
3 * IRC Services is copyright (c) 1996-2009 Andrew Church.
4 * E-mail: <achurch@achurch.org>
5 * Parts written by Andrew Kempe and others.
6 * This program is free but copyrighted software; see the file GPL.txt for
7 * details.
8 */
9
10 #include "services.h"
11 #include <setjmp.h>
12
13 /*************************************************************************/
14
15 /* If we get a signal, use this to jump out of the main loop. */
16 static sigjmp_buf *panic_ptr = NULL;
17
18 /*************************************************************************/
19 /*************************************************************************/
20
21 /* Various signal handlers. */
22
23 /*************************************************************************/
24
25 /* SIGHUP = save databases and rehash configuration files */
26 static void
27 sighup_handler(int sig_unused)
28 {
29 signal(SIGHUP, SIG_IGN); /* in case we get double signalled */
30 log("Received SIGHUP, saving data and rehashing.");
31 wallops(NULL,
32 "Received SIGHUP, saving data and rehashing configuration files");
33 save_data_now();
34 reconfigure();
35 signal(SIGHUP, sighup_handler);
36 }
37
38 /*************************************************************************/
39
40 /* SIGTERM = save databases and shut down */
41 static void
42 sigterm_handler(int sig_unused)
43 {
44 save_data = 1;
45 delayed_quit = 1;
46 signal(SIGTERM, SIG_IGN);
47 signal(SIGHUP, SIG_IGN);
48 log("Received SIGTERM, exiting.");
49 strbcpy(quitmsg, "Shutting down on SIGTERM");
50 siglongjmp(*panic_ptr, 1);
51 }
52
53 /*************************************************************************/
54
55 /* SIGUSR2 = close and reopen log file */
56 static void
57 sigusr2_handler(int sig_unused)
58 {
59 log("Received SIGUSR2, cycling log file.");
60 if (log_is_open())
61 {
62 close_log();
63 open_log();
64 }
65 signal(SIGUSR2, sigusr2_handler);
66 }
67
68 /*************************************************************************/
69
70 /* If we get a weird signal, come here. */
71 static void
72 weirdsig_handler(int signum)
73 {
74 static int dying = 0; /* Flag to avoid infinite recursion */
75
76 if (dying++)
77 {
78 /* Double signal, give up. Set `servsock' to NULL to avoid a
79 * message going out that way, just in case the socket code is
80 * confused/broken */
81 servsock = NULL;
82 if (signum == SIGUSR2)
83 {
84 fatal("Out of memory while shutting down");
85 }
86 else
87 {
88 #if HAVE_STRSIGNAL
89 fatal("Caught signal %d (%s) while shutting down", signum,
90 strsignal(signum));
91 #else
92 fatal("Caught signal %d while shutting down", signum);
93 #endif
94 }
95 }
96
97 /* Avoid spurious keyboard signals killing us while shutting down */
98 signal(SIGINT, SIG_IGN);
99 signal(SIGQUIT, SIG_IGN);
100 signal(SIGTSTP, SIG_IGN);
101
102 /* If we died processing a message, let people know about it */
103 if (signum != SIGINT && signum != SIGQUIT)
104 {
105 if (*inbuf)
106 {
107 log("PANIC! signal %d, buffer = %s", signum, inbuf);
108 /* Cut off if this would make IRC command >510 characters. */
109 if (strlen(inbuf) > 448)
110 {
111 inbuf[446] = '>';
112 inbuf[447] = '>';
113 inbuf[448] = 0;
114 }
115 wallops(NULL, "PANIC! buffer = %s\r\n", inbuf);
116 }
117 else
118 {
119 log("PANIC! signal %d (no buffer)", signum);
120 wallops(NULL, "PANIC! signal %d (no buffer)", signum);
121 }
122 }
123
124 /* Pick an appropriate quit message */
125 if (signum == SIGUSR1)
126 {
127 strbcpy(quitmsg, "Out of memory!");
128 quitting = 1;
129 }
130 else
131 {
132 #if HAVE_STRSIGNAL
133 snprintf(quitmsg, sizeof(quitmsg),
134 "Services terminating: %s", strsignal(signum));
135 #else
136 snprintf(quitmsg, sizeof(quitmsg),
137 "Services terminating on signal %d", signum);
138 #endif
139 quitting = 1;
140 }
141
142 /* Actually quit */
143 if (panic_ptr)
144 {
145 siglongjmp(*panic_ptr, 1);
146 }
147 else
148 {
149 log("%s", quitmsg);
150 if (isatty(2))
151 fprintf(stderr, "%s\n", quitmsg);
152 exit(1);
153 }
154 }
155
156 /*************************************************************************/
157 /*************************************************************************/
158
159 /* Set up signal handlers. Catch certain signals to let us do things or
160 * panic as necessary, and ignore all others.
161 */
162
163 void
164 init_signals(void)
165 {
166 int i;
167
168 /* Start out with special signals disabled */
169 disable_signals();
170
171 /* Set all signals to "ignore" */
172 for (i = 1; i <= NSIG; i++)
173 {
174 #if DUMPCORE
175 if (i != SIGSEGV)
176 #endif
177 if (i != SIGPROF && i != SIGCHLD)
178 signal(i, SIG_IGN);
179 }
180
181 /* Specify particular signals we want to catch */
182
183 /* Signals that probably mean bad things have happened */
184 #if !DUMPCORE
185 signal(SIGSEGV, weirdsig_handler);
186 #endif
187 signal(SIGBUS, weirdsig_handler);
188 signal(SIGILL, weirdsig_handler);
189 signal(SIGTRAP, weirdsig_handler);
190 signal(SIGFPE, weirdsig_handler);
191 #ifdef SIGIOT
192 signal(SIGIOT, weirdsig_handler);
193 #endif
194
195 /* This is our "out-of-memory" panic switch */
196 signal(SIGUSR1, weirdsig_handler);
197
198 /* Other special handlers */
199 signal(SIGTERM, sigterm_handler);
200 signal(SIGINT, weirdsig_handler);
201 signal(SIGQUIT, weirdsig_handler);
202 signal(SIGHUP, sighup_handler);
203 signal(SIGUSR2, sigusr2_handler);
204
205 }
206
207 /*************************************************************************/
208
209 /* Helper routine for main.c's DO_SIGSETJMP() macro; saves a pointer to the
210 * environment buffer locally.
211 */
212
213 void
214 do_sigsetjmp(void *bufptr)
215 {
216 panic_ptr = bufptr;
217 }
218
219 /*************************************************************************/
220
221 /* Enable or disable receipt of certain signals (in particular, those which
222 * cause us to take actions other than simply terminating the program, to
223 * avoid such signals happening at inopportune times and causing things to
224 * break).
225 */
226
227 void
228 enable_signals(void)
229 {
230 sigset_t sigs;
231 sigemptyset(&sigs);
232 sigaddset(&sigs, SIGHUP);
233 sigaddset(&sigs, SIGTERM);
234 sigaddset(&sigs, SIGUSR2);
235 sigprocmask(SIG_UNBLOCK, &sigs, NULL);
236 }
237
238
239 void
240 disable_signals(void)
241 {
242 sigset_t sigs;
243 sigemptyset(&sigs);
244 sigaddset(&sigs, SIGHUP);
245 sigaddset(&sigs, SIGTERM);
246 sigaddset(&sigs, SIGUSR2);
247 sigprocmask(SIG_BLOCK, &sigs, NULL);
248 }
249
250 /*************************************************************************/
251
252 /*
253 * Local variables:
254 * c-file-style: "stroustrup"
255 * c-file-offsets: ((case-label . *) (statement-case-intro . *))
256 * indent-tabs-mode: nil
257 * End:
258 *
259 * vim: expandtab shiftwidth=4:
260 */