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

Contents of /hydra/src/signals.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.26 - (show annotations)
Thu Mar 9 18:26:30 2006 UTC (18 years ago) by nmav
Branch: MAIN
CVS Tags: hydra_0_1_8, HEAD
Changes since 1.25: +3 -1 lines
File MIME type: text/plain
--disable-smp option now works.

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.25 2006-03-09 18:11:07 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
47 /*
48 * Name: init_signals
49 * Description: Sets up signal handlers for all our friends.
50 */
51
52 void init_signals(void)
53 {
54 struct sigaction sa;
55
56 sa.sa_flags = 0;
57
58 sigemptyset(&sa.sa_mask);
59 sigaddset(&sa.sa_mask, SIGSEGV);
60 sigaddset(&sa.sa_mask, SIGBUS);
61 sigaddset(&sa.sa_mask, SIGTERM);
62 sigaddset(&sa.sa_mask, SIGHUP);
63 sigaddset(&sa.sa_mask, SIGINT);
64 sigaddset(&sa.sa_mask, SIGPIPE);
65 sigaddset(&sa.sa_mask, SIGCHLD);
66 sigaddset(&sa.sa_mask, SIGALRM);
67 sigaddset(&sa.sa_mask, SIGUSR1);
68 sigaddset(&sa.sa_mask, SIGUSR2);
69
70 sa.sa_handler = sigsegv;
71 sigaction(SIGSEGV, &sa, NULL);
72
73 sa.sa_handler = sigbus;
74 sigaction(SIGBUS, &sa, NULL);
75
76 sa.sa_handler = SIG_IGN;
77 sigaction(SIGPIPE, &sa, NULL);
78
79 sa.sa_handler = sigchld;
80 sigaction(SIGCHLD, &sa, NULL);
81
82 sa.sa_handler = sigterm;
83 sigaction(SIGTERM, &sa, NULL);
84
85 sa.sa_handler = sighup;
86 sigaction(SIGHUP, &sa, NULL);
87
88 sa.sa_handler = sigint;
89 sigaction(SIGINT, &sa, NULL);
90
91 sa.sa_handler = sigalrm;
92 sigaction(SIGALRM, &sa, NULL);
93
94 sa.sa_handler = sigusr1;
95 sigaction(SIGUSR1, &sa, NULL);
96
97 }
98
99 /* Blocks all signals that should be handled by
100 * the main thread, so that other threads are
101 * not annoyed.
102 */
103 void block_main_signals()
104 {
105 sigset_t sigset;
106
107 sigemptyset(&sigset);
108 sigaddset(&sigset, SIGALRM);
109 sigaddset(&sigset, SIGUSR1);
110 sigaddset(&sigset, SIGUSR2);
111 sigaddset(&sigset, SIGTERM);
112 sigaddset(&sigset, SIGINT);
113
114 sigprocmask(SIG_BLOCK, &sigset, NULL);
115 }
116
117 void unblock_main_signals()
118 {
119 sigset_t sigset;
120
121 sigemptyset(&sigset);
122 sigaddset(&sigset, SIGALRM);
123 sigaddset(&sigset, SIGUSR1);
124 sigaddset(&sigset, SIGUSR2);
125 sigaddset(&sigset, SIGTERM);
126 sigaddset(&sigset, SIGHUP);
127 sigaddset(&sigset, SIGINT);
128
129 sigprocmask(SIG_UNBLOCK, &sigset, NULL);
130 }
131
132 void block_sigusr2()
133 {
134 sigset_t sigset;
135
136 sigemptyset(&sigset);
137 sigaddset(&sigset, SIGUSR2);
138
139 sigprocmask(SIG_BLOCK, &sigset, NULL);
140 }
141
142 void unblock_sigusr2()
143 {
144 sigset_t sigset;
145
146 sigemptyset(&sigset);
147 sigaddset(&sigset, SIGUSR2);
148
149 sigprocmask(SIG_UNBLOCK, &sigset, NULL);
150 }
151
152
153 void sigsegv(int dummy)
154 {
155 time(&current_time);
156 log_error_time();
157 fprintf(stderr, "caught SIGSEGV, dumping core in %s\n", tempdir);
158 fclose(stderr);
159 chdir(tempdir);
160 abort();
161 }
162
163 void sigbus(int dummy)
164 {
165 server_params *params = &global_server_params[0];
166
167 /* Note that in multithreaded cases the SIGBUS is catched
168 * by the same thread that did the violation. So the following
169 * code should be ok.
170 */
171
172 #ifdef ENABLE_SMP
173 pthread_t tid = pthread_self();
174 int i;
175
176 for (i = 0; i < global_server_params_size; i++) {
177 if (pthread_equal(global_server_params[i].tid, tid)) {
178 params = &global_server_params[i];
179 break;
180 }
181 }
182 #endif
183
184 if (params->handle_sigbus) {
185 longjmp(params->env, dummy);
186 }
187 time(&current_time);
188 log_error_time();
189 fprintf(stderr, "caught SIGBUS, dumping core in %s\n", tempdir);
190 fclose(stderr);
191 chdir(tempdir);
192 abort();
193 }
194
195 #define SET_PTH_SIGFLAG( flag, val) \
196 global_server_params[0].flag = val
197
198 #ifdef ENABLE_SMP
199 # define _SET_LOCAL_PTH_SIGFLAG( flag, val) \
200 { pthread_t tid = pthread_self(); int i; int set = 0; \
201 for (i=0;i<global_server_params_size;i++) { \
202 if ( pthread_equal( global_server_params[i].tid, tid)) { \
203 global_server_params[i].flag = val; \
204 set = 1; \
205 break; \
206 } \
207 }
208
209 # define SET_LOCAL_PTH_SIGFLAG( flag, val) \
210 _SET_LOCAL_PTH_SIGFLAG( flag, val) }
211
212 #else
213 # define SET_LOCAL_PTH_SIGFLAG SET_PTH_SIGFLAG
214 #endif
215
216 void sigterm(int dummy)
217 {
218 SET_PTH_SIGFLAG(sigterm_flag, 1);
219 }
220
221
222 void sigterm_stage1_run()
223 { /* lame duck mode */
224 #ifdef ENABLE_SMP
225 int i;
226 #endif
227
228 time(&current_time);
229 log_error_time();
230 fputs("caught SIGTERM, starting shutdown\n", stderr);
231
232 #ifdef ENABLE_SMP
233 {
234 int ret;
235 /* remember that the first thread is actual the main process.
236 */
237 for (i = 1; i < global_server_params_size; i++) {
238 /* terminate all threads */
239 if ((ret = pthread_cancel(global_server_params[i].tid)) != 0) {
240 log_error_time();
241 fprintf(stderr, "Could not cancel thread: %d. errno = %d.\n",
242 (int) global_server_params[i].tid, ret);
243 exit(1);
244 }
245 }
246 }
247 #endif
248
249 if (global_server_params[0].server_s[0].socket != -1) {
250 close(global_server_params[0].server_s[0].socket);
251 }
252
253 if (global_server_params[0].server_s[1].socket != -1) {
254 close(global_server_params[0].server_s[1].socket);
255 }
256
257 SET_PTH_SIGFLAG(sigterm_flag, 2);
258 }
259
260
261 void sigterm_stage2_run()
262 { /* lame duck mode */
263 int i;
264
265 log_error_time();
266 fprintf(stderr,
267 "exiting Hydra normally (uptime %d seconds)\n",
268 (int) (current_time - start_time));
269 chdir(tempdir);
270 clear_common_env();
271 dump_mime();
272 dump_passwd();
273 dump_virthost();
274 dump_directory_index();
275 dump_cgi_action_modules();
276
277 for (i = 0; i < global_server_params_size; i++) {
278 free_requests(&global_server_params[i]);
279 }
280
281 exit(0);
282 }
283
284
285 void sighup(int dummy)
286 {
287 SET_LOCAL_PTH_SIGFLAG(sighup_flag, 1);
288 }
289
290 void sighup_run()
291 {
292 int i;
293
294 /* In sighup case, the father frees all memory, and
295 * the childen terminate.
296 */
297
298 SET_LOCAL_PTH_SIGFLAG(sighup_flag, 0);
299
300
301 #ifdef ENABLE_SMP
302 /* Kill all threads! */
303 if (pthread_self() == father_id) {
304 int ret;
305
306 time(&current_time);
307 log_error_time();
308 fputs("caught SIGHUP, restarting\n", stderr);
309
310 for (i = 1; i < global_server_params_size; i++) {
311 if ((ret = pthread_kill(global_server_params[i].tid, SIGHUP)) != 0) {
312 log_error_time();
313 fprintf(stderr, "Could not kill thread: %d. errno = %d.\n",
314 (int) global_server_params[i].tid, ret);
315 } else
316 if ((ret=pthread_join( global_server_params[i].tid, NULL)) != 0) {
317 log_error_time();
318 fprintf(stderr, "Could not join thread: %d. errno = %d.\n",
319 (int) global_server_params[i].tid, ret);
320 }
321 }
322 log_error_time();
323 fputs("Terminated all the threads in the pool.\n", stderr);
324
325 for (i = 0; i < global_server_params_size; i++) {
326 free_requests(&global_server_params[i]);
327 }
328
329 #endif
330 for (i = 0; i < global_server_params_size; i++) {
331 BOA_FD_ZERO(&global_server_params[i].block_read_fdset);
332 BOA_FD_ZERO(&global_server_params[i].block_write_fdset);
333 }
334
335 /* Philosophy change for 0.92: don't close and attempt reopen of logfiles,
336 * since usual permission structure prevents such reopening.
337 */
338
339 /* clear_common_env(); NEVER DO THIS */
340 dump_mime();
341 dump_passwd();
342 dump_virthost();
343 dump_directory_index();
344 dump_cgi_action_modules();
345
346 log_error_time();
347 fputs("re-reading configuration files\n", stderr);
348 read_config_files();
349
350 /* We now need to dispatch the threads again */
351 smp_reinit();
352 ssl_reinit();
353 mmap_reinit();
354
355 log_error_time();
356 fputs("successful restart\n", stderr);
357
358 #ifdef ENABLE_SMP
359 } else { /* a normal thread -- not father */
360 pthread_exit(NULL);
361 }
362 #endif
363
364 }
365
366 void sigint(int dummy)
367 {
368 time(&current_time);
369 log_error_time();
370 fputs("caught SIGINT: shutting down\n", stderr);
371 fclose(stderr);
372 chdir(tempdir);
373 exit(1);
374 }
375
376 void sigchld(int dummy)
377 {
378 SET_LOCAL_PTH_SIGFLAG(sigchld_flag, 1);
379 }
380
381 void sigchld_run(void)
382 {
383 int status;
384 pid_t pid;
385
386 SET_LOCAL_PTH_SIGFLAG(sigchld_flag, 0);
387
388 while ((pid = waitpid(-1, &status, WNOHANG)) > 0)
389 if (verbose_cgi_logs) {
390 time(&current_time);
391 log_error_time();
392 fprintf(stderr, "reaping child %d: status %d\n", (int) pid,
393 status);
394 }
395 return;
396 }
397
398 void sigalrm(int dummy)
399 {
400 SET_PTH_SIGFLAG(sigalrm_flag, 1);
401 }
402
403 void sigusr2(int dummy)
404 {
405 return;
406 }
407
408 void sigusr1(int dummy)
409 {
410 SET_PTH_SIGFLAG(sigusr1_flag, 1);
411 }
412
413 #ifdef ENABLE_SMP
414 extern pthread_mutex_t mmap_lock;
415 #endif
416
417 void sigalrm_run(void)
418 {
419 SET_PTH_SIGFLAG(sigalrm_flag, 0);
420
421 #ifdef ENABLE_SSL
422 if (boa_ssl)
423 ssl_regenerate_params();
424 #endif
425
426 log_error_time();
427 fprintf(stderr, "Cleaning up file caches.\n");
428 #ifdef ENABLE_SMP
429 pthread_mutex_lock(&mmap_lock);
430 #endif
431 /* Clear all unused entries in the mmap list */
432 cleanup_mmap_list(1);
433 #ifdef ENABLE_SMP
434 pthread_mutex_unlock(&mmap_lock);
435 #endif
436
437 if (maintenance_interval)
438 alarm(maintenance_interval);
439
440 }
441
442 void sigusr1_run(void)
443 {
444 int i;
445
446 SET_PTH_SIGFLAG(sigusr1_flag, 0);
447
448 time(&current_time);
449
450 for (i = 0; i < global_server_params_size; i++) {
451 log_error_time();
452 fprintf(stderr, "Thread %d: %ld requests, %ld errors\n",
453 i + 1, global_server_params[i].status.requests,
454 global_server_params[i].status.errors);
455 }
456
457 /* Only print the running connections if we have set a connection
458 * limit. That is because we do not count connections when we
459 * have no connection limits.
460 */
461 if (max_connections != INT_MAX) {
462 log_error_time();
463 fprintf(stderr, "Running connections: %ld\n",
464 get_total_global_connections(0));
465 }
466
467 #ifdef ENABLE_SSL
468 if ( max_ssl_connections != INT_MAX) {
469 log_error_time();
470 fprintf(stderr, "Running SSL connections: %ld\n",
471 get_total_global_connections(1));
472 }
473 #endif
474
475 show_hash_stats();
476
477 }

webmaster@linux.gr
ViewVC Help
Powered by ViewVC 1.1.26