]> granicus.if.org Git - apache/commitdiff
If a child is created just before graceful restart and then exits because
authorStefan Fritsch <sf@apache.org>
Sun, 9 Oct 2011 23:10:12 +0000 (23:10 +0000)
committerStefan Fritsch <sf@apache.org>
Sun, 9 Oct 2011 23:10:12 +0000 (23:10 +0000)
of a missing lock file, don't shutdown the whole server.

PR: 39311
Submitted by: Shawn Michael <smichael rightnow com>

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

CHANGES
server/mpm/event/event.c
server/mpm/prefork/prefork.c
server/mpm/worker/worker.c

diff --git a/CHANGES b/CHANGES
index ffa8ca9ef0157d2ab2280726164d5f44beea4ba1..267245f57f25f2e22d219e2461dd4b357223bf78 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -12,6 +12,11 @@ Changes with Apache 2.3.15
      PR 51714. [Stefan Fritsch, Jim Jagielski, Ruediger Pluem, Eric Covener,
      <lowprio20 gmail.com>]
 
+  *) mpm_prefork, mpm_worker, mpm_event: If a child is created just before
+     graceful restart and then exits because of a missing lock file, don't
+     shutdown the whole server. PR 39311. [Shawn Michael
+     <smichael rightnow com>]
+
   *) mpm_event: Check the return value from ap_run_create_connection.
      PR: 41194. [Davi Arnaut]
 
index 38b70dee5a9b05a979cd9368dabe68d2d1f153ad..86f589ad988dfce4b801320b2191721db7a5578d 100644 (file)
@@ -2421,10 +2421,27 @@ static void server_main_loop(int remaining_children_to_start)
 
         if (pid.pid != -1) {
             processed_status = ap_process_child_status(&pid, exitwhy, status);
+            child_slot = ap_find_child_by_pid(&pid);
             if (processed_status == APEXIT_CHILDFATAL) {
-                shutdown_pending = 1;
-                child_fatal = 1;
-                return;
+                /* fix race condition found in PR 39311
+                 * A child created at the same time as a graceful happens 
+                 * can find the lock missing and create a fatal error.
+                 * It is not fatal for the last generation to be in this state.
+                 */
+                if (child_slot < 0
+                    || ap_get_scoreboard_process(child_slot)->generation
+                       == retained->my_generation) {
+                    shutdown_pending = 1;
+                    child_fatal = 1;
+                    return;
+                }
+                else {
+                    ap_log_error(APLOG_MARK, APLOG_WARNING, 0, ap_server_conf,
+                                 "Ignoring fatal error in child of previous "
+                                 "generation (pid %ld).",
+                                 (long)pid.pid);
+                    retained->sick_child_detected = 1;
+                }
             }
             else if (processed_status == APEXIT_CHILDSICK) {
                 /* tell perform_idle_server_maintenance to check into this
@@ -2433,7 +2450,6 @@ static void server_main_loop(int remaining_children_to_start)
                 retained->sick_child_detected = 1;
             }
             /* non-fatal death... note that it's gone in the scoreboard. */
-            child_slot = ap_find_child_by_pid(&pid);
             if (child_slot >= 0) {
                 for (i = 0; i < threads_per_child; i++)
                     ap_update_child_status_from_indexes(child_slot, i,
index 93dd65a8e18295fe9e2c2a894c0ce2e6a45de22d..5c382c92c87834a30a9956807d9679d5ce184e72 100644 (file)
@@ -1004,13 +1004,28 @@ static int prefork_run(apr_pool_t *_pconf, apr_pool_t *plog, server_rec *s)
          */
         if (pid.pid != -1) {
             processed_status = ap_process_child_status(&pid, exitwhy, status);
+            child_slot = ap_find_child_by_pid(&pid);
             if (processed_status == APEXIT_CHILDFATAL) {
-                mpm_state = AP_MPMQ_STOPPING;
-                return DONE;
+                /* fix race condition found in PR 39311
+                 * A child created at the same time as a graceful happens 
+                 * can find the lock missing and create a fatal error.
+                 * It is not fatal for the last generation to be in this state.
+                 */
+                if (child_slot < 0
+                    || ap_get_scoreboard_process(child_slot)->generation
+                       == retained->my_generation) {
+                    mpm_state = AP_MPMQ_STOPPING;
+                    return DONE;
+                }
+                else {
+                    ap_log_error(APLOG_MARK, APLOG_WARNING, 0, ap_server_conf,
+                                 "Ignoring fatal error in child of previous "
+                                 "generation (pid %ld).",
+                                 (long)pid.pid);
+                }
             }
 
             /* non-fatal death... note that it's gone in the scoreboard. */
-            child_slot = ap_find_child_by_pid(&pid);
             if (child_slot >= 0) {
                 (void) ap_update_child_status_from_indexes(child_slot, 0, SERVER_DEAD,
                                                            (request_rec *) NULL);
index f9c9f889bba5db6b8c7c26624040201b47281767..64612ac79c20c49b0ed89d41952fcdd51c0afab4 100644 (file)
@@ -1647,10 +1647,27 @@ static void server_main_loop(int remaining_children_to_start)
 
         if (pid.pid != -1) {
             processed_status = ap_process_child_status(&pid, exitwhy, status);
+            child_slot = ap_find_child_by_pid(&pid);
             if (processed_status == APEXIT_CHILDFATAL) {
-                shutdown_pending = 1;
-                child_fatal = 1;
-                return;
+                /* fix race condition found in PR 39311
+                 * A child created at the same time as a graceful happens 
+                 * can find the lock missing and create a fatal error.
+                 * It is not fatal for the last generation to be in this state.
+                 */
+                if (child_slot < 0
+                    || ap_get_scoreboard_process(child_slot)->generation
+                       == retained->my_generation) {
+                    shutdown_pending = 1;
+                    child_fatal = 1;
+                    return;
+                }
+                else {
+                    ap_log_error(APLOG_MARK, APLOG_WARNING, 0, ap_server_conf,
+                                 "Ignoring fatal error in child of previous "
+                                 "generation (pid %ld).",
+                                 (long)pid.pid);
+                    retained->sick_child_detected = 1;
+                }
             }
             else if (processed_status == APEXIT_CHILDSICK) {
                 /* tell perform_idle_server_maintenance to check into this
@@ -1659,7 +1676,6 @@ static void server_main_loop(int remaining_children_to_start)
                 retained->sick_child_detected = 1;
             }
             /* non-fatal death... note that it's gone in the scoreboard. */
-            child_slot = ap_find_child_by_pid(&pid);
             if (child_slot >= 0) {
                 for (i = 0; i < threads_per_child; i++)
                     ap_update_child_status_from_indexes(child_slot, i, SERVER_DEAD,