From 11b03c4294d78ba6c5c5baf1a03ce664a8f3e063 Mon Sep 17 00:00:00 2001 From: Bill Stoddard Date: Wed, 10 Mar 2004 15:05:52 +0000 Subject: [PATCH] Win32: Tweak worker thread accounting to fix hang when number of Listen directives is >= ThreadsPerChild git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@102922 13f79535-47bb-0310-9956-ffa450edef68 --- CHANGES | 4 ++++ server/mpm/winnt/child.c | 25 +++++++++++++++++++++---- 2 files changed, 25 insertions(+), 4 deletions(-) diff --git a/CHANGES b/CHANGES index adac282caf..78b0370820 100644 --- a/CHANGES +++ b/CHANGES @@ -1,6 +1,10 @@ Changes with Apache 2.1.0-dev [Remove entries to the current 2.0 section below, when backported] + *) Win32: Tweak worker thread accounting routines to eliminate + server hang when number of Listen directives in httpd.conf + is greater than or equal to the setting of ThreadsPerChild. + [Bill Stoddard] *) mod_rewrite: Support for recognizing SSL variables in RewriteCond using the new "SSL:" format. [Joe Orton, Madhusudan Mathihalli] diff --git a/server/mpm/winnt/child.c b/server/mpm/winnt/child.c index b6f9e5f96a..76ab5b45c4 100644 --- a/server/mpm/winnt/child.c +++ b/server/mpm/winnt/child.c @@ -63,6 +63,7 @@ static apr_thread_mutex_t *qlock; static PCOMP_CONTEXT qhead = NULL; static PCOMP_CONTEXT qtail = NULL; static int num_completion_contexts = 0; +static int max_num_completion_contexts = 0; static HANDLE ThreadDispatchIOCP = NULL; static HANDLE qwait_event = NULL; @@ -111,11 +112,12 @@ AP_DECLARE(PCOMP_CONTEXT) mpm_get_completion_context(void) apr_thread_mutex_unlock(qlock); if (!context) { - /* We failed to grab a context off the queue, consider allocating a - * new one out of the child pool. There may be up to ap_threads_per_child - * contexts in the system at once. + /* We failed to grab a context off the queue, consider allocating + * a new one out of the child pool. There may be up to + * (ap_threads_per_child + num_listeners) contexts in the system + * at once. */ - if (num_completion_contexts >= ap_threads_per_child) { + if (num_completion_contexts >= max_num_completion_contexts) { /* All workers are busy, need to wait for one */ static int reported = 0; if (!reported) { @@ -811,6 +813,7 @@ static void cleanup_thread(HANDLE *handles, int *thread_cnt, int thread_to_clean static void create_listener_thread() { int tid; + int num_listeners = 0; if (!use_acceptex) { _beginthreadex(NULL, 0, (LPTHREAD_START_ROUTINE) win9x_accept, NULL, 0, &tid); @@ -819,6 +822,20 @@ static void create_listener_thread() * XXX: Why would we have a NULL sd in our listeners? */ ap_listen_rec *lr; + + /* Number of completion_contexts allowed in the system is + * (ap_threads_per_child + num_listeners). We need the additional + * completion contexts to prevent server hangs when ThreadsPerChild + * is configured to something less than or equal to the number + * of listeners. This is not a usual case, but people have + * encountered it. + * */ + for (lr = ap_listeners; lr ; lr = lr->next) { + num_listeners++; + } + max_num_completion_contexts = ap_threads_per_child + num_listeners; + + /* Now start a thread per listener */ for (lr = ap_listeners; lr; lr = lr->next) { if (lr->sd != NULL) { _beginthreadex(NULL, 1000, (LPTHREAD_START_ROUTINE) winnt_accept, -- 2.50.1