From: Bill Stoddard Date: Wed, 17 Oct 2001 14:45:29 +0000 (+0000) Subject: Win32: The Apache Win32 developers generally recommend that X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=86bd8bef038940573ebb6696d75ba6a387093cb1;p=thirdparty%2Fapache%2Fhttpd.git Win32: The Apache Win32 developers generally recommend that MaxRequestsPerChild be set to 0 to prevent the child process from ever recycling. However, for those that do require a non-zero setting, this patch fixes a serious bug that can cause an apparent 'server-hang' condition where the server stops responding to requests for a period of time. Prior to this fix, when the child process handled MaxRequestsPerChild connnections, the child process would stop accepting new connections and begin allowing inactive threads to exit. The problem was that a new process would not be created to begin handling requests until the old process fully exited. The old process can take an indeterminate amount of time to exit because it may be sending large responses to clients connected over slow links, or it may have threads blocked in read awaiting requests (eg, one attack mode of the Nimda worm is to establish a connection to the server but not send an HTTP request. This connection will be timed out according to the setting of the Timeout directive, 300 seconds). This fix allows the new process to be immediately started and begin accepting requests when the old child process reaches MaxRequestsPerChild. git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/branches/1.3.x@91523 13f79535-47bb-0310-9956-ffa450edef68 --- diff --git a/src/CHANGES b/src/CHANGES index 2ec5c567995..0937e2e5e79 100644 --- a/src/CHANGES +++ b/src/CHANGES @@ -1,4 +1,26 @@ Changes with Apache 1.3.23 + *) Win32: The Apache Win32 developers generally recommend that + MaxRequestsPerChild be set to 0 to prevent the child process + from ever recycling. However, for those that do require a + non-zero setting, this patch fixes a serious bug that can cause + an apparent 'server-hang' condition where the server stops + responding to requests for a period of time. Prior to this + fix, when the child process handled MaxRequestsPerChild + connnections, the child process would stop accepting new + connections and begin allowing inactive threads to exit. The + problem was that a new process would not be created to begin + handling requests until the old process fully exited. The old + process can take an indeterminate amount of time to exit because + it may be sending large responses to clients connected over slow + links, or it may have threads blocked in read awaiting requests + (eg, one attack mode of the Nimda worm is to establish a + connection to the server but not send an HTTP request. This + connection will be timed out according to the setting of the + Timeout directive, 300 seconds). This fix allows the new process + to be immediately started and begin accepting requests when the + old child process reaches MaxRequestsPerChild. + [Bill Stoddard] + *) Win32: Emit error message when the server bumps up against the ThreadsPerChild configuration limit. This will be useful for admins to detect when their server is running out of threads diff --git a/src/main/http_main.c b/src/main/http_main.c index a58bd684950..425e2d88d29 100644 --- a/src/main/http_main.c +++ b/src/main/http_main.c @@ -5616,8 +5616,8 @@ int remove_job(int csd) if (!reported && (active_threads == ap_threads_per_child)) { reported = 1; ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, server_conf, - "server reached ThreadsPerChild setting, consider" - " raising the ThreadsPerChild setting"); + "Server ran out of threads to serve requests. Consider " + "raising the ThreadsPerChild setting"); } return (sock); } @@ -6279,8 +6279,10 @@ void worker_main(void) while (1) { if (max_jobs_per_exe && (total_jobs > max_jobs_per_exe)) { - /* MaxRequestsPerChild hit... + /* Reached MaxRequestsPerChild. Stop accepting new connections + * and signal the parent to start a new child process. */ + ap_start_restart(1); break; } /* Always check for the exit event being signaled. @@ -6796,7 +6798,11 @@ int master_main(int argc, char **argv) } break; } else if (cld == current_live_processes+1) { - /* apPID_restart event signalled, restart the child process */ + /* apPID_restart event signalled. + * Signal the child to shutdown and start a new child process. + * The restart event can be signaled by a command line restart or + * by the child process when it handles MaxRequestPerChild connections. + */ int children_to_kill = current_live_processes; restart_pending = 1; ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_INFO, server_conf, @@ -6814,17 +6820,15 @@ int master_main(int argc, char **argv) /* Remove the process (and event) from the process table */ cleanup_process(process_handles, process_kill_events, i, ¤t_live_processes); } - processes_to_create = nchild; + processes_to_create = 1; ++ap_my_generation; continue; } else { - /* A child process must have exited because of MaxRequestPerChild being hit - * or a fatal error condition (seg fault, etc.). Remove the dead process - * from the process_handles and process_kill_events table and create a new - * child process. + /* The child process exited premeturely because of a fatal error condition + * (eg, seg fault). Cleanup and restart the child process. */ ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_INFO, server_conf, - "master_main: Child processed exited (due to MaxRequestsPerChild?). Restarting the child process."); + "master_main: Child processed exited prematurely. Restarting the child process."); ap_assert(cld < current_live_processes); cleanup_process(process_handles, process_kill_events, cld, ¤t_live_processes); APD2("main_process: child in slot %d died", rv);