This was lately reported to me (privately) with the root cause being
r1819855 ([1], present in 2.4.x too) setting workers_were_busy=1 when
connections_above_limit() is reached.

Before r1819855, the #connections limit (based on
AsyncRequestWorkerFactor) only caused listening sockets to be
"paused", while now it also causes existing keepalive connections to
be early terminated (see [2]), while the docs for
AsyncRequestWorkerFactor state that it only happens when "all workers
are busy".

Since (I think) there is no point in killing connections before it's
really needed (workers exhausted), I'm about to restore the original
behaviour with the attached patch, WDYT?

Regards;
Yann.

[1] 
https://github.com/apache/httpd/commit/49b0ef1e914369678dd7001ad78f88fac4c1802a#diff-895d7e9f8add746606c82027dabc04d4R2031
[2] https://github.com/apache/httpd/blob/trunk/server/mpm/event/event.c#L2208
Index: server/mpm/event/event.c
===================================================================
--- server/mpm/event/event.c	(revision 1879949)
+++ server/mpm/event/event.c	(working copy)
@@ -534,7 +534,7 @@ static APR_INLINE apr_uint32_t listeners_disabled(
     return apr_atomic_read32(&listensocks_disabled);
 }
 
-static APR_INLINE int connections_above_limit(void)
+static APR_INLINE int connections_above_limit(int *busy)
 {
     apr_uint32_t i_count = ap_queue_info_num_idlers(worker_queue_info);
     if (i_count > 0) {
@@ -548,6 +548,9 @@ static APR_INLINE apr_uint32_t listeners_disabled(
             return 0;
         }
     }
+    else if (busy) {
+        *busy = 1;
+    }
     return 1;
 }
 
@@ -809,7 +812,7 @@ static apr_status_t decrement_connection_count(voi
     is_last_connection = !apr_atomic_dec32(&connection_count);
     if (listener_is_wakeable
             && ((is_last_connection && listener_may_exit)
-                || (listeners_disabled() && !connections_above_limit()))) {
+                || (listeners_disabled() && !connections_above_limit(NULL)))) {
         apr_pollset_wakeup(event_pollset);
     }
     return APR_SUCCESS;
@@ -2066,7 +2069,7 @@ static void * APR_THREAD_FUNC listener_thread(apr_
                                  "All workers busy, not accepting new conns "
                                  "in this process");
                 }
-                else if (connections_above_limit()) {
+                else if (connections_above_limit(&workers_were_busy)) {
                     disable_listensocks();
                     ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, ap_server_conf,
                                  APLOGNO(03269)
@@ -2076,7 +2079,6 @@ static void * APR_THREAD_FUNC listener_thread(apr_
                     ap_log_error(APLOG_MARK, APLOG_TRACE1, 0, ap_server_conf,
                                  "Idle workers: %u",
                                  ap_queue_info_num_idlers(worker_queue_info));
-                    workers_were_busy = 1;
                 }
                 else if (!listener_may_exit) {
                     void *csd = NULL;
@@ -2257,7 +2259,7 @@ static void * APR_THREAD_FUNC listener_thread(apr_
 
         if (listeners_disabled()
                 && !workers_were_busy
-                && !connections_above_limit()) {
+                && !connections_above_limit(NULL)) {
             enable_listensocks();
         }
     } /* listener main loop */

Reply via email to