dgaudet 97/11/03 02:11:44
Modified: src CHANGES src/main http_main.c Log: Fix a mild race condition in unblock_alarms() involving a SIGALRM showing up after a SIGTERM. PR: 1211 Reviewed by: Marc Slemko, Martin Kraemer Revision Changes Path 1.484 +3 -0 apachen/src/CHANGES Index: CHANGES =================================================================== RCS file: /export/home/cvs/apachen/src/CHANGES,v retrieving revision 1.483 retrieving revision 1.484 diff -u -r1.483 -r1.484 --- CHANGES 1997/11/03 04:33:16 1.483 +++ CHANGES 1997/11/03 10:11:39 1.484 @@ -1,5 +1,8 @@ Changes with Apache 1.3b3 + *) A mild SIGTERM/SIGALRM race condition was eliminated. + [Dean Gaudet] PR#1211 + *) Warn user that default path has changed if /usr/local/etc/httpd is found on the system. [Lars Eilebrecht] 1.243 +28 -27 apachen/src/main/http_main.c Index: http_main.c =================================================================== RCS file: /export/home/cvs/apachen/src/main/http_main.c,v retrieving revision 1.242 retrieving revision 1.243 diff -u -r1.242 -r1.243 --- http_main.c 1997/11/01 22:15:59 1.242 +++ http_main.c 1997/11/03 10:11:42 1.243 @@ -678,6 +678,14 @@ } #endif +/* a clean exit from a child with proper cleanup */ +static void __attribute__((noreturn)) clean_child_exit(int code) +{ + child_exit_modules(pconf, server_conf); + destroy_pool(pconf); + exit(code); +} + void timeout(int sig) { /* Also called on SIGPIPE */ char errstr[MAX_STRING_LEN]; @@ -688,6 +696,9 @@ alarm_pending = 1; return; } + if (exit_after_unblock) { + clean_child_exit(0); + } if (!current_conn) { ap_longjmp(jmpbuffer, 1); @@ -760,10 +771,16 @@ --alarms_blocked; if (alarms_blocked == 0) { if (exit_after_unblock) { + /* We have a couple race conditions to deal with here, we can't + * allow a timeout that comes in this small interval to allow + * the child to jump back to the main loop. Instead we block + * alarms again, and then note that exit_after_unblock is + * being dealt with. We choose this way to solve this so that + * the common path through unblock_alarms() is really short. + */ + ++alarms_blocked; exit_after_unblock = 0; - child_exit_modules(pconf, server_conf); - destroy_pool(pconf); - exit(0); + clean_child_exit(0); } if (alarm_pending) { alarm_pending = 0; @@ -1964,9 +1981,7 @@ exit_after_unblock = 1; } else { - child_exit_modules(pconf, server_conf); - destroy_pool(pconf); - exit(0); + clean_child_exit(0); } } @@ -2668,16 +2683,12 @@ sync_scoreboard_image(); if (scoreboard_image->global.exit_generation >= generation) { - child_exit_modules(pconf, server_conf); - destroy_pool(pconf); - exit(0); + clean_child_exit(0); } if ((max_requests_per_child > 0 && ++requests_this_child >= max_requests_per_child)) { - child_exit_modules(pconf, server_conf); - destroy_pool(pconf); - exit(0); + clean_child_exit(0); } (void) update_child_status(my_child_num, SERVER_READY, (request_rec *) NULL); @@ -2700,9 +2711,7 @@ if (errno == EFAULT) { aplog_error(APLOG_MARK, APLOG_ERR, server_conf, "select: (listen) fatal, child exiting"); - child_exit_modules(pconf, server_conf); - destroy_pool(pconf); - exit(1); + clean_child_exit(1); } #endif aplog_error(APLOG_MARK, APLOG_ERR, server_conf, "select: (listen)"); @@ -2733,9 +2742,7 @@ break; if (deferred_die) { /* we didn't get a socket, and we were told to die */ - child_exit_modules(pconf, server_conf); - destroy_pool(pconf); - exit(0); + clean_child_exit(0); } } @@ -2758,18 +2765,14 @@ usr1_just_die = 1; if (deferred_die) { /* ok maybe not, see ya later */ - child_exit_modules(pconf, server_conf); - destroy_pool(pconf); - exit(0); + clean_child_exit(0); } /* or maybe we missed a signal, you never know on systems * without reliable signals */ sync_scoreboard_image(); if (scoreboard_image->global.exit_generation >= generation) { - child_exit_modules(pconf, server_conf); - destroy_pool(pconf); - exit(0); + clean_child_exit(0); } } @@ -2855,9 +2858,7 @@ sync_scoreboard_image(); if (scoreboard_image->global.exit_generation >= generation) { bclose(conn_io); - child_exit_modules(pconf, server_conf); - destroy_pool(pconf); - exit(0); + clean_child_exit(0); } /* In case we get a graceful restart while we're blocked