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]
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;
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) {
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);
* 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,