From 7d0348cd7881374af07999cfcb936b2b79d4e6b2 Mon Sep 17 00:00:00 2001 From: Stefan Fritsch Date: Sun, 9 Oct 2011 23:10:12 +0000 Subject: [PATCH] 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 Submitted by: Shawn Michael git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1180742 13f79535-47bb-0310-9956-ffa450edef68 --- CHANGES | 5 +++++ server/mpm/event/event.c | 24 ++++++++++++++++++++---- server/mpm/prefork/prefork.c | 21 ++++++++++++++++++--- server/mpm/worker/worker.c | 24 ++++++++++++++++++++---- 4 files changed, 63 insertions(+), 11 deletions(-) diff --git a/CHANGES b/CHANGES index ffa8ca9ef0..267245f57f 100644 --- a/CHANGES +++ b/CHANGES @@ -12,6 +12,11 @@ Changes with Apache 2.3.15 PR 51714. [Stefan Fritsch, Jim Jagielski, Ruediger Pluem, Eric Covener, ] + *) 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 + ] + *) mpm_event: Check the return value from ap_run_create_connection. PR: 41194. [Davi Arnaut] diff --git a/server/mpm/event/event.c b/server/mpm/event/event.c index 38b70dee5a..86f589ad98 100644 --- a/server/mpm/event/event.c +++ b/server/mpm/event/event.c @@ -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, diff --git a/server/mpm/prefork/prefork.c b/server/mpm/prefork/prefork.c index 93dd65a8e1..5c382c92c8 100644 --- a/server/mpm/prefork/prefork.c +++ b/server/mpm/prefork/prefork.c @@ -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); diff --git a/server/mpm/worker/worker.c b/server/mpm/worker/worker.c index f9c9f889bb..64612ac79c 100644 --- a/server/mpm/worker/worker.c +++ b/server/mpm/worker/worker.c @@ -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, -- 2.40.0