]> git.ipfire.org Git - thirdparty/apache/httpd.git/commitdiff
Backport r239710, r239711, r239732, r239740 and r241815 to the 2.2.x branch;
authorColm MacCarthaigh <colm@apache.org>
Mon, 19 Sep 2005 14:57:07 +0000 (14:57 +0000)
committerColm MacCarthaigh <colm@apache.org>
Mon, 19 Sep 2005 14:57:07 +0000 (14:57 +0000)
Fix PR 28167, which means we stop listening on ports when we do a
graceful-restart.

git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/branches/2.2.x@290179 13f79535-47bb-0310-9956-ffa450edef68

CHANGES
include/ap_listen.h
modules/generators/mod_cgid.c
server/listen.c
server/mpm/experimental/event/event.c
server/mpm/prefork/prefork.c
server/mpm/worker/worker.c

diff --git a/CHANGES b/CHANGES
index fb733180ae7d0028cd9229b2c906b4e430030fe9..f07ddf5806a7eb126946be72e4388c5232f1c0ae 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -1,6 +1,10 @@
                                                         -*- coding: utf-8 -*-
 Changes with Apache 2.1.8
 
+  *) prefork, worker and event MPMs: Prevent children from holding open 
+     listening ports upon graceful restart or stop. PR 28167. 
+     [Colm MacCarthaigh, Brian Pinkerton <bp thinkpink.com>]
+
   *) SECURITY: CAN-2005-2700 (cve.mitre.org)
      mod_ssl: Fix a security issue where "SSLVerifyClient" was not
      enforced in per-location context if "SSLVerifyClient optional"
index d98949f37923decff97fbd1fbd781a1915ea4572..6182a8917d9c8f13f70c9bc3fcc613c7a3c1adcc 100644 (file)
@@ -77,6 +77,11 @@ AP_DECLARE(void) ap_listen_pre_config(void);
  */ 
 AP_DECLARE(int) ap_setup_listeners(server_rec *s);
 
+/**
+ * Loop through the global ap_listen_rec list and close each of the sockets.
+ */
+AP_DECLARE_NONSTD(void) ap_close_listeners(void);
+
 /* Although these functions are exported from libmain, they are not really
  * public functions.  These functions are actually called while parsing the
  * config file, when one of the LISTEN_COMMANDS directives is read.  These
index 1299f4c45daf0fffb16edfc5c66df54913dd695d..110e4a49d91b961e81586e3bdb8c81d09904aded 100644 (file)
@@ -566,6 +566,9 @@ static int cgid_server(void *data)
     apr_signal(SIGCHLD, SIG_IGN); 
     apr_signal(SIGHUP, daemon_signal_handler);
 
+    /* Close our copy of the listening sockets */
+    ap_close_listeners();
+
     /* cgid should use its own suexec doer */
     ap_hook_get_suexec_identity(cgid_suexec_id_doer, NULL, NULL,
                                 APR_HOOK_REALLY_FIRST);
index 6d557430690623302bb5add7b82a4927f1a06804..f95e0f61107840f2a431f6334a06d09a0bb496bc 100644 (file)
@@ -237,17 +237,10 @@ static void ap_apply_accept_filter(apr_pool_t *p, ap_listen_rec *lis,
 
 static apr_status_t close_listeners_on_exec(void *v)
 {
-    ap_listen_rec *lr;
-
-    for (lr = ap_listeners; lr; lr = lr->next) {
-        apr_socket_close(lr->sd);
-        lr->active = 0;
-    }
-
+    ap_close_listeners();
     return APR_SUCCESS;
 }
 
-
 static const char *alloc_listener(process_rec *process, char *addr, 
                                   apr_port_t port, const char* proto)
 {
@@ -568,6 +561,15 @@ AP_DECLARE(int) ap_setup_listeners(server_rec *s)
     return num_listeners;
 }
 
+AP_DECLARE_NONSTD(void) ap_close_listeners(void) {
+    ap_listen_rec *lr;
+
+    for (lr = ap_listeners; lr; lr = lr->next) {
+        apr_socket_close(lr->sd);
+        lr->active = 0;
+    }
+}
+
 AP_DECLARE(void) ap_listen_pre_config(void)
 {
     old_listeners = ap_listeners;
index 45d8458290f5c887fdf88ec341f9da1b0be657f4..299cdf856f9630baad7b052058b1a9b6f650b4e9 100644 (file)
@@ -1036,6 +1036,7 @@ static void *listener_thread(apr_thread_t * thd, void *dummy)
 
     }     /* listener main loop */
 
+    ap_close_listeners();
     ap_queue_term(worker_queue);
     dying = 1;
     ap_scoreboard_image->parent[process_slot].quiescing = 1;
index 8776f32616e95e5d696a7e49a64febff94b0db86..41a54866b3134efd31c8b45c969dabdca4431e6c 100644 (file)
@@ -328,6 +328,11 @@ static void just_die(int sig)
     clean_child_exit(0);
 }
 
+static void stop_listening(int sig)
+{
+    ap_close_listeners();
+}
+
 /* volatile just in case */
 static int volatile shutdown_pending;
 static int volatile restart_pending;
@@ -712,10 +717,10 @@ static int make_child(server_rec *s, int slot)
          */
         apr_signal(SIGHUP, just_die);
         apr_signal(SIGTERM, just_die);
-        /* The child process doesn't do anything for AP_SIG_GRACEFUL.  
-         * Instead, the pod is used for signalling graceful restart.
+        /* The child process just closes listeners on AP_SIG_GRACEFUL.  
+         * The pod is used for signalling graceful restart.
          */
-        apr_signal(AP_SIG_GRACEFUL, SIG_IGN);
+        apr_signal(AP_SIG_GRACEFUL, stop_listening);
         child_main(slot);
     }
 
@@ -1093,6 +1098,7 @@ int ap_mpm_run(apr_pool_t *_pconf, apr_pool_t *plog, server_rec *s)
 
     /* we've been told to restart */
     apr_signal(SIGHUP, SIG_IGN);
+    apr_signal(AP_SIG_GRACEFUL, SIG_IGN);
     if (one_process) {
         /* not worth thinking about */
         return 1;
@@ -1120,6 +1126,14 @@ int ap_mpm_run(apr_pool_t *_pconf, apr_pool_t *plog, server_rec *s)
         for (index = 0; index < ap_daemons_limit; ++index) {
             if (ap_scoreboard_image->servers[index][0].status != SERVER_DEAD) {
                 ap_scoreboard_image->servers[index][0].status = SERVER_GRACEFUL;
+                /* Ask each child to close its listeners.
+                 *
+                 * NOTE: we use the scoreboard, because if we send SIGUSR1
+                 * to every process in the group, this may include CGI's,
+                 * piped loggers, etc. They almost certainly won't handle
+                 * it gracefully.
+                 */
+                kill(ap_scoreboard_image->parent[index].pid, AP_SIG_GRACEFUL);
             }
         }
     }
index 1380ee23b523ecb8f330f5ab6d2684d57eb4a07b..904ef4a9028b4bf8fd571a01dd6e0fba3be3d0b0 100644 (file)
@@ -775,6 +775,7 @@ static void *listener_thread(apr_thread_t *thd, void * dummy)
         }
     }
 
+    ap_close_listeners();
     ap_queue_term(worker_queue);
     dying = 1;
     ap_scoreboard_image->parent[process_slot].quiescing = 1;