]> granicus.if.org Git - apache/commitdiff
Fix a hang condition with graceful restart and prefork MPM
authorJeff Trawick <trawick@apache.org>
Mon, 18 Mar 2002 18:24:55 +0000 (18:24 +0000)
committerJeff Trawick <trawick@apache.org>
Mon, 18 Mar 2002 18:24:55 +0000 (18:24 +0000)
in the situation where MaxClients is very high but
much fewer servers are actually started at the time of the
restart.

The way we notify an entire generation to die at once is
changed so that we don't have to use the pod (and deal with
the ease of filling the kernel pipe buffer).

git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@93999 13f79535-47bb-0310-9956-ffa450edef68

CHANGES
server/mpm/prefork/prefork.c
server/mpm_common.c

diff --git a/CHANGES b/CHANGES
index f3d07bc23cfaa116a55e9373d70139e727d13278..d48b4eb5316166460f55e908edbae210d1d46e9a 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -1,5 +1,10 @@
 Changes with Apache 2.0.34-dev
 
+  *) Fix a hang condition with graceful restart and prefork MPM
+     in the situation where MaxClients is very high but
+     much fewer servers are actually started at the time of the
+     restart.  [Jeff Trawick]
+
   *) Small performance fixes for mod_include [Brian Pane]
 
   *) Performance improvement for the error logger [Brian Pane]
index 43121289b30b8cf51f198941b29b85a3007da7e7..80c73de297722c0eb400326d77dcb9069cc134b1 100644 (file)
@@ -675,14 +675,19 @@ static void child_main(int child_num_arg)
             ap_lingering_close(current_conn);
         }
         
-        /* Check the pod after processing a connection so that we'll go away
-         * if a graceful restart occurred while we were processing the 
-         * connection.  Otherwise, we won't wake up until a real connection 
-         * comes in and we'll use the wrong config to process it and we may
-         * block in the wrong syscall (because the new generation is using a
-         * different accept mutex) and in general it is goofy.
+        /* Check the pod and the generation number after processing a
+         * connection so that we'll go away if a graceful restart occurred
+         * while we were processing the connection or we are the lucky
+         * idle server process that gets to die.
          */
-        if (!ap_mpm_pod_check(pod)) {
+        if (ap_mpm_pod_check(pod) == APR_SUCCESS) { /* selected as idle? */
+            die_now = 1;
+        }
+        else if (ap_my_generation !=
+                 ap_scoreboard_image->global->running_generation) { /* restart? */
+            /* yeah, this could be non-graceful restart, in which case the
+             * parent will kill us soon enough, but why bother checking?
+             */
             die_now = 1;
         }
         ap_sync_scoreboard_image();
index 6e9f23a51d2e71451e80feb5ba87c683d6818a30..66a1d25a0b4e7d59b5933fe63e529ec11b0f63c0 100644 (file)
@@ -540,14 +540,21 @@ void ap_mpm_pod_killpg(ap_pod_t *pod, int num)
     int i;
     apr_status_t rv = APR_SUCCESS;
 
+    /* we don't write anything to the pod here...  we assume
+     * that the would-be reader of the pod has another way to
+     * see that it is time to die once we wake it up
+     *
+     * writing lots of things to the pod at once is very
+     * problematic... we can fill the kernel pipe buffer and
+     * be blocked until somebody consumes some bytes or
+     * we hit a timeout...  if we hit a timeout we can't just
+     * keep trying because maybe we'll never successfully
+     * write again...  but then maybe we'll leave would-be
+     * readers stranded (a number of them could be tied up for
+     * a while serving time-consuming requests)
+     */
     for (i = 0; i < num && rv == APR_SUCCESS; i++) {
-        rv = pod_signal_internal(pod);
-    }
-
-    if (rv == APR_SUCCESS) {
-        for (i = 0; i < num && rv == APR_SUCCESS; i++) {
-             rv = dummy_connection(pod);
-        }
+        rv = dummy_connection(pod);
     }
 }
 #endif /* #ifdef AP_MPM_USES_POD */