]> granicus.if.org Git - apache/commitdiff
end-generation hook: Fix false notification of end-of-generation for
authorJeff Trawick <trawick@apache.org>
Thu, 10 Nov 2011 17:46:57 +0000 (17:46 +0000)
committerJeff Trawick <trawick@apache.org>
Thu, 10 Nov 2011 17:46:57 +0000 (17:46 +0000)
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

CHANGES
include/mpm_common.h
server/core.c
server/mpm_common.c

diff --git a/CHANGES b/CHANGES
index 9b3118eb0a3bafa613e34bb79a23b0f7edbc8b5e..1e5b0a59f42dae3d9020c01e3fa7395cbdf30ed1 100644 (file)
--- 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]
 
index f342c290abefce08901032c7fd2a3773dd489ee5..e6700264ec43293c2a42c00859fa0072b6b3da74 100644 (file)
@@ -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.
index dc068432699ca39cefc6d8f7fdcc1f5bc06d4671..751c32219b441115b32838404b7497bc65bd62ab 100644 (file)
@@ -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;
 }
 
index d189920072561d66b8b2b06427cc9a3ec4abf45b..3663167fc313330dbc352390f32775b81d49d910 100644 (file)
@@ -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;