summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeff Trawick <trawick@apache.org>2011-11-10 17:46:57 +0000
committerJeff Trawick <trawick@apache.org>2011-11-10 17:46:57 +0000
commit5405226ae2190c03dc84c816a709d3b8187c7218 (patch)
tree81f6f94dcb4de9fc910e8d3bc694ed9d5c96e1e0
parente66f481ac366291f70cea605b65fb937ea3899cc (diff)
downloadhttpd-5405226ae2190c03dc84c816a709d3b8187c7218.tar.gz
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
-rw-r--r--CHANGES3
-rw-r--r--include/mpm_common.h5
-rw-r--r--server/core.c2
-rw-r--r--server/mpm_common.c53
4 files changed, 56 insertions, 7 deletions
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
@@ -137,6 +137,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.
* @param pid the process id of a child process to signal
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;