/[hydra]/hydra/src/signals.c
ViewVC logotype

Contents of /hydra/src/signals.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.20 - (show annotations)
Thu Oct 10 11:54:35 2002 UTC (21 years, 6 months ago) by nmav
Branch: MAIN
CVS Tags: hydra_0_0_7
Changes since 1.19: +3 -3 lines
File MIME type: text/plain
fixed the printing of alert message.

1 /*
2 * Hydra, an http server
3 * Copyright (C) 1995 Paul Phillips <paulp@go2net.com>
4 * Some changes Copyright (C) 1996 Larry Doolittle <ldoolitt@boa.org>
5 * Some changes Copyright (C) 1996-99 Jon Nelson <jnelson@boa.org>
6 * Some changes Copyright (C) 1997 Alain Magloire <alain.magloire@rcsm.ee.mcgill.ca>
7 * Portions Copyright (C) 2002 Nikos Mavroyanopoulos <nmav@gnutls.org>
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 1, or (at your option)
12 * any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 *
23 */
24
25 /* $Id: signals.c,v 1.19 2002/10/09 08:49:46 nmav Exp $*/
26
27 #include "boa.h"
28 #ifdef HAVE_SYS_WAIT_H
29 #include <sys/wait.h> /* wait */
30 #endif
31 #include <signal.h> /* signal */
32 #include "ssl.h"
33
34 #ifdef ENABLE_SMP
35 extern pthread_t father_id;
36 #endif
37
38 void sigsegv(int);
39 void sigbus(int);
40 void sigterm(int);
41 void sighup(int);
42 void sigint(int);
43 void sigchld(int);
44 void sigalrm(int);
45 void sigusr1(int);
46 void sigusr2(int); /* needed in HIC thread */
47
48 /*
49 * Name: init_signals
50 * Description: Sets up signal handlers for all our friends.
51 */
52
53 void init_signals(void)
54 {
55 struct sigaction sa;
56
57 sa.sa_flags = 0;
58
59 sigemptyset(&sa.sa_mask);
60 sigaddset(&sa.sa_mask, SIGSEGV);
61 sigaddset(&sa.sa_mask, SIGBUS);
62 sigaddset(&sa.sa_mask, SIGTERM);
63 sigaddset(&sa.sa_mask, SIGHUP);
64 sigaddset(&sa.sa_mask, SIGINT);
65 sigaddset(&sa.sa_mask, SIGPIPE);
66 sigaddset(&sa.sa_mask, SIGCHLD);
67 sigaddset(&sa.sa_mask, SIGALRM);
68 sigaddset(&sa.sa_mask, SIGUSR1);
69 sigaddset(&sa.sa_mask, SIGUSR2);
70
71 sa.sa_handler = sigsegv;
72 sigaction(SIGSEGV, &sa, NULL);
73
74 sa.sa_handler = sigbus;
75 sigaction(SIGBUS, &sa, NULL);
76
77 sa.sa_handler = SIG_IGN;
78 sigaction(SIGPIPE, &sa, NULL);
79
80 sa.sa_handler = sigchld;
81 sigaction(SIGCHLD, &sa, NULL);
82
83 sa.sa_handler = sigterm;
84 sigaction(SIGTERM, &sa, NULL);
85
86 sa.sa_handler = sighup;
87 sigaction(SIGHUP, &sa, NULL);
88
89 sa.sa_handler = sigint;
90 sigaction(SIGINT, &sa, NULL);
91
92 sa.sa_handler = sigalrm;
93 sigaction(SIGALRM, &sa, NULL);
94
95 sa.sa_handler = sigusr1;
96 sigaction(SIGUSR1, &sa, NULL);
97
98 sa.sa_handler = sigusr2;
99 sigaction(SIGUSR2, &sa, NULL);
100 }
101
102 /* Blocks all signals that should be handled by
103 * the main thread, so that other threads are
104 * not annoyed.
105 */
106 void block_main_signals()
107 {
108 sigset_t sigset;
109
110 sigemptyset(&sigset);
111 sigaddset(&sigset, SIGALRM);
112 sigaddset(&sigset, SIGUSR1);
113 sigaddset(&sigset, SIGUSR2);
114 sigaddset(&sigset, SIGTERM);
115 sigaddset(&sigset, SIGINT);
116
117 sigprocmask(SIG_BLOCK, &sigset, NULL);
118 }
119
120 void unblock_main_signals()
121 {
122 sigset_t sigset;
123
124 sigemptyset(&sigset);
125 sigaddset(&sigset, SIGALRM);
126 sigaddset(&sigset, SIGUSR1);
127 sigaddset(&sigset, SIGUSR2);
128 sigaddset(&sigset, SIGTERM);
129 sigaddset(&sigset, SIGHUP);
130 sigaddset(&sigset, SIGINT);
131
132 sigprocmask(SIG_UNBLOCK, &sigset, NULL);
133 }
134
135 void block_sigusr2()
136 {
137 sigset_t sigset;
138
139 sigemptyset(&sigset);
140 sigaddset(&sigset, SIGUSR2);
141
142 sigprocmask(SIG_BLOCK, &sigset, NULL);
143 }
144
145 void unblock_sigusr2()
146 {
147 sigset_t sigset;
148
149 sigemptyset(&sigset);
150 sigaddset(&sigset, SIGUSR2);
151
152 sigprocmask(SIG_UNBLOCK, &sigset, NULL);
153 }
154
155
156 void sigsegv(int dummy)
157 {
158 time(&current_time);
159 log_error_time();
160 fprintf(stderr, "caught SIGSEGV, dumping core in %s\n", tempdir);
161 fclose(stderr);
162 chdir(tempdir);
163 abort();
164 }
165
166 void sigbus(int dummy)
167 {
168 server_params *params = &global_server_params[0];
169
170 /* Note that in multithreaded cases the SIGBUS is catched
171 * by the same thread that did the violation. So the following
172 * code should be ok.
173 */
174
175 #ifdef ENABLE_SMP
176 pthread_t tid = pthread_self();
177 int i;
178
179 for (i = 0; i < global_server_params_size; i++) {
180 if (pthread_equal(global_server_params[i].tid, tid)) {
181 params = &global_server_params[i];
182 break;
183 }
184 }
185 #endif
186
187 if (params->handle_sigbus) {
188 longjmp(params->env, dummy);
189 }
190 time(&current_time);
191 log_error_time();
192 fprintf(stderr, "caught SIGBUS, dumping core in %s\n", tempdir);
193 fclose(stderr);
194 chdir(tempdir);
195 abort();
196 }
197
198 #define SET_PTH_SIGFLAG( flag, val) \
199 global_server_params[0].flag = val
200
201 #ifdef ENABLE_SMP
202 # define _SET_LOCAL_PTH_SIGFLAG( flag, val) \
203 { pthread_t tid = pthread_self(); int i; int set = 0; \
204 for (i=0;i<global_server_params_size;i++) { \
205 if ( pthread_equal( global_server_params[i].tid, tid)) { \
206 global_server_params[i].flag = val; \
207 set = 1; \
208 break; \
209 } \
210 }
211
212 # ifdef ENABLE_HIC
213 # define SET_LOCAL_PTH_SIGFLAG( flag, val) \
214 _SET_LOCAL_PTH_SIGFLAG( flag, val) \
215 \
216 if (!set) { /* try hic threads */ \
217 for (i=0;i<global_hic_params_size;i++) { \
218 if ( pthread_equal( global_hic_params[i].tid, tid)) { \
219 global_hic_params[i].flag = val; \
220 break; \
221 } \
222 } \
223 } \
224 }
225 # else
226
227 # define SET_LOCAL_PTH_SIGFLAG( flag, val) \
228 _SET_LOCAL_PTH_SIGFLAG( flag, val) }
229
230 # endif
231
232 #else
233 # define SET_LOCAL_PTH_SIGFLAG SET_PTH_SIGFLAG
234 #endif
235
236 void sigterm(int dummy)
237 {
238 SET_PTH_SIGFLAG(sigterm_flag, 1);
239 }
240
241
242 void sigterm_stage1_run()
243 { /* lame duck mode */
244 #ifdef ENABLE_SMP
245 int i;
246 #endif
247
248 time(&current_time);
249 log_error_time();
250 fputs("caught SIGTERM, starting shutdown\n", stderr);
251
252 #ifdef ENABLE_SMP
253 {
254 int ret;
255 /* remember that the first thread is actual the main process.
256 */
257 for (i = 1; i < global_server_params_size; i++) {
258 /* terminate all threads */
259 if ((ret = pthread_cancel(global_server_params[i].tid)) != 0) {
260 log_error_time();
261 fprintf(stderr, "Could not cancel thread: %d. errno = %d.\n",
262 (int) global_server_params[i].tid, ret);
263 exit(1);
264 }
265 }
266
267 # ifdef ENABLE_HIC
268 for (i = 0; i < global_hic_params_size; i++) {
269 if ((ret = pthread_cancel(global_hic_params[i].tid)) != 0) {
270 log_error_time();
271 fprintf(stderr, "Could not cancel thread: %d. errno = %d.\n",
272 (int) global_hic_params[i].tid, ret);
273 exit(1);
274 }
275 }
276 # endif
277 }
278 #endif
279
280 if (global_server_params[0].server_s[0].socket != -1) {
281 FD_CLR(global_server_params[0].server_s[0].socket,
282 &global_server_params[0].block_read_fdset);
283 close(global_server_params[0].server_s[0].socket);
284 }
285
286 if (global_server_params[0].server_s[1].socket != -1) {
287 FD_CLR(global_server_params[0].server_s[1].socket,
288 &global_server_params[0].block_read_fdset);
289 close(global_server_params[0].server_s[1].socket);
290 }
291
292 SET_PTH_SIGFLAG(sigterm_flag, 2);
293 }
294
295
296 void sigterm_stage2_run()
297 { /* lame duck mode */
298 int i;
299
300 log_error_time();
301 fprintf(stderr,
302 "exiting Hydra normally (uptime %d seconds)\n",
303 (int) (current_time - start_time));
304 chdir(tempdir);
305 clear_common_env();
306 dump_mime();
307 dump_passwd();
308 dump_virthost();
309 dump_directory_index();
310 dump_hic_modules();
311
312 for (i = 0; i < global_server_params_size; i++) {
313 free_requests(&global_server_params[i]);
314 }
315
316 exit(0);
317 }
318
319
320 void sighup(int dummy)
321 {
322 SET_LOCAL_PTH_SIGFLAG(sighup_flag, 1);
323 }
324
325 void sighup_run()
326 {
327 int i;
328
329 /* In sighup case, the father frees all memory, and
330 * the childen terminate.
331 */
332
333 SET_LOCAL_PTH_SIGFLAG(sighup_flag, 0);
334
335
336 #ifdef ENABLE_SMP
337 /* Kill all threads! */
338 if (pthread_self() == father_id) {
339 int ret;
340
341 time(&current_time);
342 log_error_time();
343 fputs("caught SIGHUP, restarting\n", stderr);
344
345 for (i = 1; i < global_server_params_size; i++) {
346 if ((ret = pthread_kill(global_server_params[i].tid, SIGHUP)) != 0) {
347 log_error_time();
348 fprintf(stderr, "Could not kill thread: %d. errno = %d.\n",
349 (int) global_server_params[i].tid, ret);
350 } else
351 if ((ret=pthread_join( global_server_params[i].tid, NULL)) != 0) {
352 log_error_time();
353 fprintf(stderr, "Could not join thread: %d. errno = %d.\n",
354 (int) global_hic_params[i].tid, ret);
355 }
356 }
357 log_error_time();
358 fputs("Terminated all the threads in the pool.\n", stderr);
359
360 # ifdef ENABLE_HIC
361 for (i = 0; i < global_hic_params_size; i++) {
362 if ((ret = pthread_kill(global_hic_params[i].tid, SIGHUP)) != 0) {
363 log_error_time();
364 fprintf(stderr, "Could not kill thread: %d. errno = %d.\n",
365 (int) global_hic_params[i].tid, ret);
366 } else
367 /* wait too see it die */
368 if ((ret=pthread_join( global_hic_params[i].tid, NULL)) != 0) {
369 log_error_time();
370 fprintf(stderr, "Could not join thread: %d. errno = %d.\n",
371 (int) global_hic_params[i].tid, ret);
372 }
373 }
374
375 log_error_time();
376 fputs("Terminated all the HIC threads.\n", stderr);
377 # endif
378
379 for (i = 0; i < global_server_params_size; i++) {
380 free_requests(&global_server_params[i]);
381 }
382
383 #endif
384 for (i = 0; i < global_server_params_size; i++) {
385 FD_ZERO(&global_server_params[i].block_read_fdset);
386 FD_ZERO(&global_server_params[i].block_write_fdset);
387 }
388
389 /* Philosophy change for 0.92: don't close and attempt reopen of logfiles,
390 * since usual permission structure prevents such reopening.
391 */
392
393 /* clear_common_env(); NEVER DO THIS */
394 dump_mime();
395 dump_passwd();
396 dump_virthost();
397 dump_directory_index();
398 dump_hic_modules();
399
400 log_error_time();
401 fputs("re-reading configuration files\n", stderr);
402 read_config_files();
403
404 /* We now need to dispatch the threads again */
405 #ifdef ENABLE_HIC
406 hic_init();
407 #endif
408 smp_reinit();
409 ssl_reinit();
410 mmap_reinit();
411
412 log_error_time();
413 fputs("successful restart\n", stderr);
414
415 } else { /* a normal thread -- not father */
416 pthread_exit(NULL);
417 }
418
419 }
420
421 void sigint(int dummy)
422 {
423 time(&current_time);
424 log_error_time();
425 fputs("caught SIGINT: shutting down\n", stderr);
426 fclose(stderr);
427 chdir(tempdir);
428 exit(1);
429 }
430
431 void sigchld(int dummy)
432 {
433 SET_LOCAL_PTH_SIGFLAG(sigchld_flag, 1);
434 }
435
436 void sigchld_run(void)
437 {
438 int status;
439 pid_t pid;
440
441 SET_LOCAL_PTH_SIGFLAG(sigchld_flag, 0);
442
443 while ((pid = waitpid(-1, &status, WNOHANG)) > 0)
444 if (verbose_cgi_logs) {
445 time(&current_time);
446 log_error_time();
447 fprintf(stderr, "reaping child %d: status %d\n", (int) pid,
448 status);
449 }
450 return;
451 }
452
453 void sigalrm(int dummy)
454 {
455 SET_PTH_SIGFLAG(sigalrm_flag, 1);
456 }
457
458 void sigusr2(int dummy)
459 {
460 return;
461 }
462
463 void sigusr1(int dummy)
464 {
465 SET_PTH_SIGFLAG(sigusr1_flag, 1);
466 }
467
468 extern int ssl_params_refresh;
469 extern int boa_ssl;
470
471 void sigalrm_run(void)
472 {
473 SET_PTH_SIGFLAG(sigalrm_flag, 0);
474
475 #ifdef ENABLE_SSL
476 if (boa_ssl)
477 ssl_regenerate_params();
478 #endif
479
480 if (boa_ssl && ssl_params_refresh)
481 alarm(ssl_params_refresh);
482 }
483
484 void sigusr1_run(void)
485 {
486 int i;
487
488 SET_PTH_SIGFLAG(sigusr1_flag, 0);
489
490 time(&current_time);
491
492 for (i = 0; i < global_server_params_size; i++) {
493 log_error_time();
494 fprintf(stderr, "Thread %d: %ld requests, %ld errors\n",
495 i + 1, global_server_params[i].status.requests,
496 global_server_params[i].status.errors);
497 }
498
499 show_hash_stats();
500
501 }

webmaster@linux.gr
ViewVC Help
Powered by ViewVC 1.1.26