]> granicus.if.org Git - apache/commitdiff
Implement graceful stop in the event MPM. Implementation is identical to
authorColm MacCarthaigh <colm@apache.org>
Mon, 29 Aug 2005 10:20:25 +0000 (10:20 +0000)
committerColm MacCarthaigh <colm@apache.org>
Mon, 29 Aug 2005 10:20:25 +0000 (10:20 +0000)
the worker MPM implementation.

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

CHANGES
docs/manual/mod/mpm_common.html.en
docs/manual/mod/mpm_common.xml
docs/manual/new_features_2_2.html.en
docs/manual/new_features_2_2.xml
docs/manual/new_features_2_2.xml.ko
docs/manual/new_features_2_2.xml.pt-br
server/mpm/experimental/event/event.c
server/mpm/experimental/event/mpm.h

diff --git a/CHANGES b/CHANGES
index aab1a3bb2fb3909cb698eff0865b43fa62e45935..8f83c3359c6ac4ac52e6f72aff71b4dd432b447d 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -4,7 +4,7 @@ Changes with Apache 2.3.0
 
   *) Doxygen fixup [Neale Ranns neale ranns.org, Ian Holsman]
 
-  *) prefork and worker MPMs: Support a graceful-stop procedure:
+  *) prefork, worker and event MPMs: Support a graceful-stop procedure:
      Server will wait until existing requests are finished or until  
      "GracefulShutdownTimeout" number of seconds before exiting. 
      [Colm MacCarthaigh, Ken Coar, Bill Stoddard]
@@ -12,8 +12,8 @@ Changes with Apache 2.3.0
   *) mod_cgid: Append .PID to the script socket filename and remove the
      script socket on exit. [Colm MacCarthaigh]
 
-  *) prefork and worker MPMs: Prevent children from holding open listening
-     ports upon graceful restart or stop. PR28167. 
+  *) prefork, worker and event MPMs: Prevent children from holding open 
+     listening ports upon graceful restart or stop. PR28167. 
      [Colm MacCarthaigh, Brian Pinkerton <bp thinkpink.com>]
 
   *) Linux 2.0: remove support for threaded MPM's due to linuxthreads use
index c8e0bb005205d9e9a0189a291332af3b47a0e7f8..d34e1fab9cc33363534adaf6ec1df6c1682b3e0a 100644 (file)
@@ -181,7 +181,7 @@ will exit.</td></tr>
 <tr><th><a href="directive-dict.html#Default">Default:</a></th><td><code>GracefulShutDownTimeout 0</code></td></tr>
 <tr><th><a href="directive-dict.html#Context">Context:</a></th><td>server config</td></tr>
 <tr><th><a href="directive-dict.html#Status">Status:</a></th><td>MPM</td></tr>
-<tr><th><a href="directive-dict.html#Module">Module:</a></th><td><code class="module"><a href="../mod/prefork.html">prefork</a></code>, <code class="module"><a href="../mod/worker.html">worker</a></code></td></tr>
+<tr><th><a href="directive-dict.html#Module">Module:</a></th><td><code class="module"><a href="../mod/prefork.html">prefork</a></code>, <code class="module"><a href="../mod/worker.html">worker</a></code>, <code class="module"><a href="../mod/event.html">event</a></code></td></tr>
 <tr><th><a href="directive-dict.html#Compatibility">Compatibility:</a></th><td>Available in version 2.2 and later</td></tr>
 </table>
     <p>The <code class="directive">GracefulShutdownTimeout</code> specifies
index d631d32d13cfa308094f3938521c32514266cb06..347f4cb6e32cac69e063c6919cca6cbe6a603699 100644 (file)
@@ -163,7 +163,8 @@ will exit.</description>
 <syntax>GracefulShutDownTimeout <var>seconds</var></syntax>
 <default>GracefulShutDownTimeout 0</default>
 <contextlist><context>server config</context></contextlist>
-<modulelist><module>prefork</module><module>worker</module></modulelist>
+<modulelist><module>prefork</module><module>worker</module>
+<module>event</module></modulelist>
 <compatibility>Available in version 2.2 and later</compatibility>
 
 <usage>
index 7ebf1b2751b02ccedb6d4b3c5104be7359b1eda2..e30b4e9b5be4b1c11cdd536a196889346f46abfc 100644 (file)
@@ -53,8 +53,9 @@
           setups.</dd>
 
       <dt>Graceful stop</dt>
-      <dd>The <code class="module"><a href="./mod/prefork.html">prefork</a></code> and <code class="module"><a href="./mod/worker.html">worker</a></code> MPMs now
-          allow <code class="program"><a href="./programs/httpd.html">httpd</a></code> to be shutdown gracefully via the
+      <dd>The <code class="module"><a href="./mod/prefork.html">prefork</a></code>, <code class="module"><a href="./mod/worker.html">worker</a></code> and 
+          <code class="module"><a href="./mod/event.html">event</a></code>  MPMs now allow <code class="program"><a href="./programs/httpd.html">httpd</a></code> 
+          to be shutdown gracefully via the
           <a href="stopping.html#gracefulstop"><code>graceful-stop</code></a> 
           signal. The <code class="directive"><a href="./mod/mpm_common.html#gracefulshutdowntimeout">GracefulShutdownTimeout</a></code> directive
           has been added to specify an optional timeout, after which
index 7a886179480068a3ba36d8923140d0509b6a00af..510e66b2de33de968bb7ff2712c9553c45e84fb7 100644 (file)
@@ -49,8 +49,9 @@
           setups.</dd>
 
       <dt>Graceful stop</dt>
-      <dd>The <module>prefork</module> and <module>worker</module> MPMs now
-          allow <program>httpd</program> to be shutdown gracefully via the
+      <dd>The <module>prefork</module>, <module>worker</module> and 
+          <module>event</module>  MPMs now allow <program>httpd</program> 
+          to be shutdown gracefully via the
           <a href="stopping.html#gracefulstop"><code>graceful-stop</code></a> 
           signal. The <directive 
           module="mpm_common">GracefulShutdownTimeout</directive> directive
index 0e8d3ab0101a6d8d7754b7fbd0ae5e3e20951130..733323c50c83a78396b28ff07ca8e9ea3fdb0d39 100644 (file)
@@ -1,7 +1,7 @@
 <?xml version='1.0' encoding='EUC-KR' ?>
 <!DOCTYPE manualpage SYSTEM "./style/manualpage.dtd">
 <?xml-stylesheet type="text/xsl" href="./style/manual.ko.xsl"?>
-<!-- English Revision: 105989:193026 (outdated) -->
+<!-- English Revision: 105989:263906 (outdated) -->
 
 <!--
  Copyright 2004-2005 The Apache Software Foundation or its licensors,
index a97474c4d3d06bbee9629268c04566754062a3fe..10a13818a8600f51f44f99db382c852619a9b42c 100644 (file)
@@ -1,7 +1,7 @@
 <?xml version='1.0' encoding='UTF-8' ?>
 <!DOCTYPE manualpage SYSTEM "./style/manualpage.dtd">
 <?xml-stylesheet type="text/xsl" href="./style/manual.pt-br.xsl"?>
-<!-- English Revision: 151408:193026 (outdated) -->
+<!-- English Revision: 151408:263906 (outdated) -->
 
 <!--
  Copyright 2005 The Apache Software Foundation or its licensors,
index 45d8458290f5c887fdf88ec341f9da1b0be657f4..3dc48e1cf14eacdf2ac492b94ad7f7053f02849d 100644 (file)
@@ -416,7 +416,7 @@ ap_generation_t volatile ap_my_generation;
  * child to force an exit) and so do an exit anyway.
  */
 
-static void ap_start_shutdown(void)
+static void ap_start_shutdown(int graceful)
 {
     mpm_state = AP_MPMQ_STOPPING;
     if (shutdown_pending == 1) {
@@ -427,6 +427,7 @@ static void ap_start_shutdown(void)
         return;
     }
     shutdown_pending = 1;
+    is_graceful = graceful;
 }
 
 /* do a graceful restart if graceful == 1 */
@@ -443,7 +444,7 @@ static void ap_start_restart(int graceful)
 
 static void sig_term(int sig)
 {
-    ap_start_shutdown();
+    ap_start_shutdown(sig == AP_SIG_GRACEFUL_STOP);
 }
 
 static void restart(int sig)
@@ -469,6 +470,11 @@ static void set_signals(void)
     if (sigaction(SIGTERM, &sa, NULL) < 0)
         ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf,
                      "sigaction(SIGTERM)");
+#ifdef AP_SIG_GRACEFUL_STOP
+    if (sigaction(AP_SIG_GRACEFUL_STOP, &sa, NULL) < 0)
+        ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf,
+                     "sigaction(" AP_SIG_GRACEFUL_STOP_STRING ")");
+#endif
 #ifdef SIGINT
     if (sigaction(SIGINT, &sa, NULL) < 0)
         ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf,
@@ -521,6 +527,9 @@ static void set_signals(void)
 #ifdef AP_SIG_GRACEFUL
     apr_signal(AP_SIG_GRACEFUL, restart);
 #endif /* AP_SIG_GRACEFUL */
+#ifdef AP_SIG_GRACEFUL_STOP
+     apr_signal(AP_SIG_GRACEFUL_STOP, sig_term);
+#endif /* AP_SIG_GRACEFUL_STOP */
 #ifdef SIGPIPE
     apr_signal(SIGPIPE, SIG_IGN);
 #endif /* SIGPIPE */
@@ -1036,6 +1045,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;
@@ -1924,11 +1934,9 @@ int ap_mpm_run(apr_pool_t * _pconf, apr_pool_t * plog, server_rec * s)
     server_main_loop(remaining_children_to_start);
     mpm_state = AP_MPMQ_STOPPING;
 
-    if (shutdown_pending) {
-        /* Time to gracefully shut down:
+    if (shutdown_pending && !is_graceful) {
+        /* Time to shut down:
          * Kill child processes, tell them to call child_exit, etc...
-         * (By "gracefully" we don't mean graceful in the same sense as 
-         * "apachectl graceful" where we allow old connections to finish.)
          */
         ap_mpm_pod_killpg(pod, ap_daemons_limit, FALSE);
         ap_reclaim_child_processes(1);  /* Start with SIGTERM */
@@ -1947,7 +1955,64 @@ int ap_mpm_run(apr_pool_t * _pconf, apr_pool_t * plog, server_rec * s)
                          ap_server_conf, "caught SIGTERM, shutting down");
         }
         return 1;
-    }
+    } else if (shutdown_pending) {
+        /* Time to gracefully shut down:
+         * Kill child processes, tell them to call child_exit, etc...
+         */
+        int active_children;
+        int index;
+        apr_time_t cutoff = 0;
+
+        /* Close our listeners, and then ask our children to do same */
+        ap_close_listeners();
+        ap_mpm_pod_killpg(pod, ap_daemons_limit, TRUE);
+        ap_relieve_child_processes();
+
+        if (!child_fatal) {
+            /* cleanup pid file on normal shutdown */
+            const char *pidfile = NULL;
+            pidfile = ap_server_root_relative (pconf, ap_pid_fname);
+            if ( pidfile != NULL && unlink(pidfile) == 0)
+                ap_log_error(APLOG_MARK, APLOG_INFO, 0,
+                             ap_server_conf,
+                             "removed PID file %s (pid=%ld)",
+                             pidfile, (long)getpid());
+
+            ap_log_error(APLOG_MARK, APLOG_NOTICE, 0,
+                         ap_server_conf, "caught SIGTERM, shutting down");
+        }
+
+        /* Don't really exit until each child has finished */
+        shutdown_pending = 0;
+        do {
+            /* Pause for a second */
+            apr_sleep(apr_time_from_sec(1));
+
+            /* Relieve any children which have now exited */
+            ap_relieve_child_processes();
+
+            active_children = 0;
+            for (index = 0; index < ap_daemons_limit; ++index) {
+                if (MPM_CHILD_PID(index) != 0) {
+                    if (kill(MPM_CHILD_PID(index), 0) == 0) {
+                            active_children = 1;
+                            /* Having just one child is enough to stay around */
+                            break;
+                    }
+                }
+            }
+        } while (!shutdown_pending && active_children &&
+                 (!ap_graceful_shutdown_timeout || apr_time_now() < cutoff));
+
+        /* We might be here because we received SIGTERM, either
+         * way, try and make sure that all of our processes are
+         * really dead.
+         */
+        ap_mpm_pod_killpg(pod, ap_daemons_limit, FALSE);
+        ap_reclaim_child_processes(1);
+
+        return 1;
+    } 
 
     /* we've been told to restart */
     apr_signal(SIGHUP, SIG_IGN);
@@ -2370,6 +2435,7 @@ static const command_rec event_cmds[] = {
     AP_INIT_TAKE1("ThreadLimit", set_thread_limit, NULL, RSRC_CONF,
                   "Maximum number of worker threads per child process for this "
                   "run of Apache - Upper limit for ThreadsPerChild"),
+    AP_GRACEFUL_SHUTDOWN_TIMEOUT_COMMAND,
     {NULL}
 };
 
index 31733690dc0f4006c579b92bf67e06cc3022fb5f..05f3c7cb9850c5e2264c1a92ebe0af5d8075bb56 100644 (file)
@@ -45,6 +45,7 @@
 #define AP_MPM_WANT_SIGNAL_SERVER
 #define AP_MPM_WANT_SET_MAX_MEM_FREE
 #define AP_MPM_WANT_SET_STACKSIZE
+#define AP_MPM_WANT_SET_GRACEFUL_SHUTDOWN
 #define AP_MPM_WANT_FATAL_SIGNAL_HANDLER
 #define AP_MPM_DISABLE_NAGLE_ACCEPTED_SOCK