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

Contents of /hydra/src/signals.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.24 - (show annotations)
Wed Jan 22 07:51:50 2003 UTC (21 years, 2 months ago) by nmav
Branch: MAIN
CVS Tags: hydra_0_1_7, hydra_0_1_6, hydra_0_1_4
Changes since 1.23: +20 -2 lines
File MIME type: text/plain
merged changes from 0.1.x branch.

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.23.2.5 2003/01/19 11:17:34 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 close(global_server_params[0].server_s[0].socket);
282 }
283
284 if (global_server_params[0].server_s[1].socket != -1) {
285 close(global_server_params[0].server_s[1].socket);
286 }
287
288 SET_PTH_SIGFLAG(sigterm_flag, 2);
289 }
290
291
292 void sigterm_stage2_run()
293 { /* lame duck mode */
294 int i;
295
296 log_error_time();
297 fprintf(stderr,
298 "exiting Hydra normally (uptime %d seconds)\n",
299 (int) (current_time - start_time));
300 chdir(tempdir);
301 clear_common_env();
302 dump_mime();
303 dump_passwd();
304 dump_virthost();
305 dump_directory_index();
306 dump_hic_modules();
307
308 for (i = 0; i < global_server_params_size; i++) {
309 free_requests(&global_server_params[i]);
310 }
311
312 exit(0);
313 }
314
315
316 void sighup(int dummy)
317 {
318 SET_LOCAL_PTH_SIGFLAG(sighup_flag, 1);
319 }
320
321 void sighup_run()
322 {
323 int i;
324
325 /* In sighup case, the father frees all memory, and
326 * the childen terminate.
327 */
328
329 SET_LOCAL_PTH_SIGFLAG(sighup_flag, 0);
330
331
332 #ifdef ENABLE_SMP
333 /* Kill all threads! */
334 if (pthread_self() == father_id) {
335 int ret;
336
337 time(&current_time);
338 log_error_time();
339 fputs("caught SIGHUP, restarting\n", stderr);
340
341 for (i = 1; i < global_server_params_size; i++) {
342 if ((ret = pthread_kill(global_server_params[i].tid, SIGHUP)) != 0) {
343 log_error_time();
344 fprintf(stderr, "Could not kill thread: %d. errno = %d.\n",
345 (int) global_server_params[i].tid, ret);
346 } else
347 if ((ret=pthread_join( global_server_params[i].tid, NULL)) != 0) {
348 log_error_time();
349 fprintf(stderr, "Could not join thread: %d. errno = %d.\n",
350 (int) global_server_params[i].tid, ret);
351 }
352 }
353 log_error_time();
354 fputs("Terminated all the threads in the pool.\n", stderr);
355
356 # ifdef ENABLE_HIC
357 for (i = 0; i < global_hic_params_size; i++) {
358 if ((ret = pthread_kill(global_hic_params[i].tid, SIGHUP)) != 0) {
359 log_error_time();
360 fprintf(stderr, "Could not kill thread: %d. errno = %d.\n",
361 (int) global_hic_params[i].tid, ret);
362 } else
363 /* wait too see it die */
364 if ((ret=pthread_join( global_hic_params[i].tid, NULL)) != 0) {
365 log_error_time();
366 fprintf(stderr, "Could not join thread: %d. errno = %d.\n",
367 (int) global_hic_params[i].tid, ret);
368 }
369 }
370
371 log_error_time();
372 fputs("Terminated all the HIC threads.\n", stderr);
373 # endif
374
375 for (i = 0; i < global_server_params_size; i++) {
376 free_requests(&global_server_params[i]);
377 }
378
379 #endif
380 for (i = 0; i < global_server_params_size; i++) {
381 BOA_FD_ZERO(&global_server_params[i].block_read_fdset);
382 BOA_FD_ZERO(&global_server_params[i].block_write_fdset);
383 }
384
385 /* Philosophy change for 0.92: don't close and attempt reopen of logfiles,
386 * since usual permission structure prevents such reopening.
387 */
388
389 /* clear_common_env(); NEVER DO THIS */
390 dump_mime();
391 dump_passwd();
392 dump_virthost();
393 dump_directory_index();
394 dump_hic_modules();
395
396 log_error_time();
397 fputs("re-reading configuration files\n", stderr);
398 read_config_files();
399
400 /* We now need to dispatch the threads again */
401 #ifdef ENABLE_HIC
402 hic_init();
403 #endif
404 smp_reinit();
405 ssl_reinit();
406 mmap_reinit();
407
408 log_error_time();
409 fputs("successful restart\n", stderr);
410
411 } else { /* a normal thread -- not father */
412 pthread_exit(NULL);
413 }
414
415 }
416
417 void sigint(int dummy)
418 {
419 time(&current_time);
420 log_error_time();
421 fputs("caught SIGINT: shutting down\n", stderr);
422 fclose(stderr);
423 chdir(tempdir);
424 exit(1);
425 }
426
427 void sigchld(int dummy)
428 {
429 SET_LOCAL_PTH_SIGFLAG(sigchld_flag, 1);
430 }
431
432 void sigchld_run(void)
433 {
434 int status;
435 pid_t pid;
436
437 SET_LOCAL_PTH_SIGFLAG(sigchld_flag, 0);
438
439 while ((pid = waitpid(-1, &status, WNOHANG)) > 0)
440 if (verbose_cgi_logs) {
441 time(&current_time);
442 log_error_time();
443 fprintf(stderr, "reaping child %d: status %d\n", (int) pid,
444 status);
445 }
446 return;
447 }
448
449 void sigalrm(int dummy)
450 {
451 SET_PTH_SIGFLAG(sigalrm_flag, 1);
452 }
453
454 void sigusr2(int dummy)
455 {
456 return;
457 }
458
459 void sigusr1(int dummy)
460 {
461 SET_PTH_SIGFLAG(sigusr1_flag, 1);
462 }
463
464 #ifdef ENABLE_SMP
465 extern pthread_mutex_t mmap_lock;
466 #endif
467
468 void sigalrm_run(void)
469 {
470 SET_PTH_SIGFLAG(sigalrm_flag, 0);
471
472 #ifdef ENABLE_SSL
473 if (boa_ssl)
474 ssl_regenerate_params();
475 #endif
476
477 log_error_time();
478 fprintf(stderr, "Cleaning up file caches.\n");
479 #ifdef ENABLE_SMP
480 pthread_mutex_lock(&mmap_lock);
481 #endif
482 /* Clear all unused entries in the mmap list */
483 cleanup_mmap_list(1);
484 #ifdef ENABLE_SMP
485 pthread_mutex_unlock(&mmap_lock);
486 #endif
487
488 if (maintenance_interval)
489 alarm(maintenance_interval);
490
491 }
492
493 void sigusr1_run(void)
494 {
495 int i;
496
497 SET_PTH_SIGFLAG(sigusr1_flag, 0);
498
499 time(&current_time);
500
501 for (i = 0; i < global_server_params_size; i++) {
502 log_error_time();
503 fprintf(stderr, "Thread %d: %ld requests, %ld errors\n",
504 i + 1, global_server_params[i].status.requests,
505 global_server_params[i].status.errors);
506 }
507
508 /* Only print the running connections if we have set a connection
509 * limit. That is because we do not count connections when we
510 * have no connection limits.
511 */
512 if (max_connections != INT_MAX) {
513 log_error_time();
514 fprintf(stderr, "Running connections: %ld\n",
515 get_total_global_connections(0));
516 }
517
518 #ifdef ENABLE_SSL
519 if ( max_ssl_connections != INT_MAX) {
520 log_error_time();
521 fprintf(stderr, "Running SSL connections: %ld\n",
522 get_total_global_connections(1));
523 }
524 #endif
525
526 show_hash_stats();
527
528 }

webmaster@linux.gr
ViewVC Help
Powered by ViewVC 1.1.26