]> granicus.if.org Git - apache/commitdiff
Implement "de-listening" for graceful restarts with the prefork MPM. With this
authorColm MacCarthaigh <colm@apache.org>
Wed, 24 Aug 2005 16:58:11 +0000 (16:58 +0000)
committerColm MacCarthaigh <colm@apache.org>
Wed, 24 Aug 2005 16:58:11 +0000 (16:58 +0000)
change;

  1.) httpd -k graceful sends SIGUSR1 to the parent pid, which in turn
      sends SIGUSR1 to all of the active children,

  2.) Active children each close their copy of listener fd's.

This means that the listening sockets are freed for re-use. In the ordinary
case, this makes no difference. However if for example admin changes "Listen
80" to "Listen 81" in the config, this rev makes port 80 immediately available
(no waiting for the graceful children to die).

git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@239711 13f79535-47bb-0310-9956-ffa450edef68

server/mpm/prefork/prefork.c

index 0afe6f0bdde10267670001425ad015de9f61582d..7ba2638bf48e3ee33c837f24d0a3a8935c329a9d 100644 (file)
@@ -331,6 +331,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;
@@ -715,10 +720,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 the graceful restart.
          */
-        apr_signal(AP_SIG_GRACEFUL, SIG_IGN);
+        apr_signal(AP_SIG_GRACEFUL, stop_listening);
         child_main(slot);
     }
 
@@ -1096,6 +1101,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;
@@ -1123,6 +1129,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);
             }
         }
     }