ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/vendor/ircservices-5.1.24/signals.c
Revision: 3389
Committed: Fri Apr 25 14:12:15 2014 UTC (9 years, 11 months ago) by michael
Content type: text/x-csrc
File size: 6664 byte(s)
Log Message:
- Imported ircservices-5.1.24

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