Return-Path: Delivered-To: apmail-apache-cvs-archive@apache.org Received: (qmail 83526 invoked by uid 500); 26 Apr 2001 18:52:32 -0000 Mailing-List: contact apache-cvs-help@apache.org; run by ezmlm Precedence: bulk Reply-To: new-httpd@apache.org list-help: list-unsubscribe: list-post: Delivered-To: mailing list apache-cvs@apache.org Received: (qmail 83493 invoked by uid 500); 26 Apr 2001 18:52:30 -0000 Delivered-To: apmail-httpd-2.0-cvs@apache.org Date: 26 Apr 2001 18:52:30 -0000 Message-ID: <20010426185230.83486.qmail@apache.org> From: gregames@apache.org To: httpd-2.0-cvs@apache.org Subject: cvs commit: httpd-2.0/server/mpm/threaded threaded.c gregames 01/04/26 11:52:30 Modified: . CHANGES server/mpm/threaded threaded.c Log: Fix shutdown/restart hangs in the threaded MPM. After removing mod_cgid from my build (thanks, Jeff), I can do: * apachectl graceful, followed by * apachectl restart, followed by * apachectl stop ...and get the results you would expect. Submitted by: Jeff Trawick, Greg Ames, Ryan Bloom Revision Changes Path 1.186 +3 -0 httpd-2.0/CHANGES Index: CHANGES =================================================================== RCS file: /home/cvs/httpd-2.0/CHANGES,v retrieving revision 1.185 retrieving revision 1.186 diff -u -d -b -u -r1.185 -r1.186 --- CHANGES 2001/04/26 00:33:07 1.185 +++ CHANGES 2001/04/26 18:52:28 1.186 @@ -1,5 +1,8 @@ Changes with Apache 2.0.18-dev + *) Fix shutdown/restart hangs in the threaded MPM. + [Jeff Trawick, Greg Ames, Ryan Bloom] + *) Removed the keptalive boolean from conn_rec because it is now only used by a single routine and can be replaced by a local variable. [Greg Stein, Ryan Bloom, Roy Fielding] 1.27 +41 -14 httpd-2.0/server/mpm/threaded/threaded.c Index: threaded.c =================================================================== RCS file: /home/cvs/httpd-2.0/server/mpm/threaded/threaded.c,v retrieving revision 1.26 retrieving revision 1.27 diff -u -d -b -u -r1.26 -r1.27 --- threaded.c 2001/04/23 23:14:35 1.26 +++ threaded.c 2001/04/26 18:52:29 1.27 @@ -705,12 +705,22 @@ /* What state should this child_main process be listed as in the scoreboard...? * ap_update_child_status(my_child_num, i, SERVER_STARTING, (request_rec *) NULL); + * + * This state should be listed separately in the scoreboard, in some kind + * of process_status, not mixed in with the worker threads' status. + * "life_status" is almost right, but it's in the worker's structure, and + * the name could be clearer. gla */ apr_signal_thread(check_signal); + workers_may_exit = 1; /* helps us terminate a little more quickly when + * the dispatch of the signal thread + * beats the Pipe of Death and the browsers + */ + /* A terminating signal was received. Now join each of the workers to clean them up. - * If the worker already exitted, then the join frees their resources and returns. + * If the worker already exited, then the join frees their resources and returns. * If the worker hasn't exited, then this blocks until they have (then cleans up). */ for (i = 0; i < ap_threads_per_child; i++) { @@ -781,6 +791,29 @@ return 0; } +/* If there aren't many connections coming in from the network, the child + * processes may need to be awakened from their network i/o waits. + * The pipe of death is an effective prod. + */ + +static void wake_up_and_die(void) +{ + int i; + char char_of_death = '!'; + apr_size_t one = 1; + apr_status_t rv; + + for (i = 0; i < ap_daemons_limit;) { + if ((rv = apr_file_write(pipe_of_death_out, &char_of_death, &one)) + != APR_SUCCESS) { + if (APR_STATUS_IS_EINTR(rv)) continue; + ap_log_error(APLOG_MARK, APLOG_WARNING, rv, ap_server_conf, + "write pipe_of_death"); + } + i++; + } +} + /* start up a bunch of children */ static void startup_children(int number_to_start) { @@ -994,7 +1027,6 @@ { int remaining_children_to_start; apr_status_t rv; - apr_size_t one = 1; pconf = _pconf; ap_server_conf = s; @@ -1078,6 +1110,8 @@ /* Time to gracefully shut down: * Kill child processes, tell them to call child_exit, etc... */ + wake_up_and_die(); + if (unixd_killpg(getpgrp(), SIGTERM) < 0) { ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "killpg SIGTERM"); } @@ -1116,21 +1150,14 @@ ap_scoreboard_image->global.running_generation = ap_my_generation; update_scoreboard_global(); + /* wake up the children...time to die. But we'll have more soon */ + wake_up_and_die(); + if (is_graceful) { int i, j; - char char_of_death = '!'; ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_NOTICE, 0, ap_server_conf, "SIGWINCH received. Doing graceful restart"); - - /* give the children the signal to die */ - for (i = 0; i < ap_daemons_limit;) { - if ((rv = apr_file_write(pipe_of_death_out, &char_of_death, &one)) != APR_SUCCESS) { - if (APR_STATUS_IS_EINTR(rv)) continue; - ap_log_error(APLOG_MARK, APLOG_WARNING, rv, ap_server_conf, "write pipe_of_death"); - } - i++; - } /* This is mostly for debugging... so that we know what is still * gracefully dealing with existing request.