From: Jeff Trawick Date: Thu, 10 Nov 2011 17:46:57 +0000 (+0000) Subject: end-generation hook: Fix false notification of end-of-generation for X-Git-Tag: 2.3.16~202 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=5405226ae2190c03dc84c816a709d3b8187c7218;p=apache end-generation hook: Fix false notification of end-of-generation for temporary intervals with no active MPM children. git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1200449 13f79535-47bb-0310-9956-ffa450edef68 --- diff --git a/CHANGES b/CHANGES index 9b3118eb0a..1e5b0a59f4 100644 --- a/CHANGES +++ b/CHANGES @@ -1,6 +1,9 @@ -*- coding: utf-8 -*- Changes with Apache 2.3.16 + *) end-generation hook: Fix false notification of end-of-generation for + temporary intervals with no active MPM children. [Jeff Trawick] + *) mod_ssl: Add support for RFC 5077 TLS Session tickets. [Paul Querna] diff --git a/include/mpm_common.h b/include/mpm_common.h index f342c290ab..e6700264ec 100644 --- a/include/mpm_common.h +++ b/include/mpm_common.h @@ -136,6 +136,11 @@ void ap_register_extra_mpm_process(pid_t pid, ap_generation_t gen); */ int ap_unregister_extra_mpm_process(pid_t pid, ap_generation_t *old_gen); +/** + * Pool cleanup for end-generation hook implementation + */ +apr_status_t ap_mpm_end_gen_helper(void *unused); + /** * Safely signal an MPM child process, if the process is in the * current process group. Otherwise fail. diff --git a/server/core.c b/server/core.c index dc06843269..751c32219b 100644 --- a/server/core.c +++ b/server/core.c @@ -4389,6 +4389,8 @@ static int core_post_config(apr_pool_t *pconf, apr_pool_t *plog, apr_pool_t *pte "or other system security module is loaded."); return !OK; } + apr_pool_cleanup_register(pconf, NULL, ap_mpm_end_gen_helper, + apr_pool_cleanup_null); return OK; } diff --git a/server/mpm_common.c b/server/mpm_common.c index d189920072..3663167fc3 100644 --- a/server/mpm_common.c +++ b/server/mpm_common.c @@ -131,6 +131,7 @@ typedef struct mpm_gen_info_t { APR_RING_ENTRY(mpm_gen_info_t) link; int gen; /* which gen? */ int active; /* number of active processes */ + int done; /* gen finished? (whether or not active processes) */ } mpm_gen_info_t; APR_RING_HEAD(mpm_gen_info_head_t, mpm_gen_info_t); @@ -413,9 +414,50 @@ AP_DECLARE(apr_status_t) ap_mpm_query(int query_code, int *result) return rv; } +static void end_gen(mpm_gen_info_t *gi) +{ + ap_log_error(APLOG_MARK, APLOG_TRACE4, 0, ap_server_conf, + "end of generation %d", gi->gen); + ap_run_end_generation(ap_server_conf, gi->gen); + APR_RING_REMOVE(gi, link); + APR_RING_INSERT_HEAD(unused_geninfo, gi, mpm_gen_info_t, link); +} + +apr_status_t ap_mpm_end_gen_helper(void *unused) /* cleanup on pconf */ +{ + int gen = ap_config_generation - 1; /* differs from MPM generation */ + mpm_gen_info_t *cur; + + if (geninfo == NULL) { + /* initial pconf teardown, MPM hasn't run */ + return APR_SUCCESS; + } + + cur = APR_RING_FIRST(geninfo); + while (cur != APR_RING_SENTINEL(geninfo, mpm_gen_info_t, link) && + cur->gen != gen) { + cur = APR_RING_NEXT(cur, link); + } + + if (cur == APR_RING_SENTINEL(geninfo, mpm_gen_info_t, link)) { + /* last child of generation already exited */ + ap_log_error(APLOG_MARK, APLOG_TRACE4, 0, ap_server_conf, + "no record of generation %d", gen); + } + else { + cur->done = 1; + if (cur->active == 0) { + end_gen(cur); + } + } + + return APR_SUCCESS; +} + /* core's child-status hook * tracks number of remaining children per generation and - * runs the end-generation hook when a generation finishes + * runs the end-generation hook when the last child of + * a generation exits */ void ap_core_child_status(server_rec *s, pid_t pid, ap_generation_t gen, int slot, @@ -446,6 +488,7 @@ void ap_core_child_status(server_rec *s, pid_t pid, if (!APR_RING_EMPTY(unused_geninfo, mpm_gen_info_t, link)) { cur = APR_RING_FIRST(unused_geninfo); APR_RING_REMOVE(cur, link); + cur->active = cur->done = 0; } else { cur = apr_pcalloc(s->process->pool, sizeof *cur); @@ -466,12 +509,8 @@ void ap_core_child_status(server_rec *s, pid_t pid, } else { --cur->active; - if (!cur->active) { - ap_log_error(APLOG_MARK, APLOG_TRACE4, 0, ap_server_conf, - "end of generation %d", gen); - ap_run_end_generation(ap_server_conf, gen); - APR_RING_REMOVE(cur, link); - APR_RING_INSERT_HEAD(unused_geninfo, cur, mpm_gen_info_t, link); + if (!cur->active && cur->done) { /* no children, server has stopped/restarted */ + end_gen(cur); } } break;