]> git.ipfire.org Git - thirdparty/apache/httpd.git/commitdiff
Changes required to make prefork clean up idle children properly. There was a window...
authorPaul J. Reder <rederpj@apache.org>
Fri, 6 Apr 2001 20:12:09 +0000 (20:12 +0000)
committerPaul J. Reder <rederpj@apache.org>
Fri, 6 Apr 2001 20:12:09 +0000 (20:12 +0000)
git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@88741 13f79535-47bb-0310-9956-ffa450edef68

include/ap_mpm.h
include/scoreboard.h
modules/generators/mod_status.c
server/mpm/prefork/prefork.c
server/mpm_common.c

index 26a4d44aa5cc92df28660b1185a1b5095580bf4d..549faf71ccbc93fdd0ee738eea5d57e088c02f88 100644 (file)
@@ -121,7 +121,7 @@ AP_DECLARE(int) ap_mpm_run(apr_pool_t *pconf, apr_pool_t *plog, server_rec *serv
  * predicate indicating if a graceful stop has been requested ...
  * used by the connection loop 
  * @return 1 if a graceful stop has been requested, 0 otherwise
- * @deffunc int ap_graceful_stop_signalled*void)
+ * @deffunc int ap_graceful_stop_signalled(*void)
  */
 AP_DECLARE(int) ap_graceful_stop_signalled(void);
 
index 91cbcf20b1098032bbd75fe8147c4cc3f2814617..81238495f242f1233f3440929d69070361f7ba77 100644 (file)
@@ -100,7 +100,8 @@ extern "C" {
 #define SERVER_GRACEFUL 8      /* server is gracefully finishing request */
 #define SERVER_ACCEPTING 9     /* thread is accepting connections */
 #define SERVER_QUEUEING        10      /* thread is putting connection on the queue */
-#define SERVER_NUM_STATUS 11   /* number of status settings */
+#define SERVER_IDLE_KILL 11     /* Server is cleaning up idle children. */
+#define SERVER_NUM_STATUS 12   /* number of status settings */
 
 /* A "virtual time" is simply a counter that indicates that a child is
  * making progress.  The parent checks up on each child, and when they have
@@ -148,6 +149,10 @@ typedef enum {
     SB_NOT_SHARED = 2
 } ap_scoreboard_e;
 
+#define SB_WORKING  0  /* The server is busy and the child is useful. */
+#define SB_IDLE_DIE 1  /* The server is idle and the child is superfluous. */
+                       /*   The child should check for this and exit gracefully. */
+
 /* stuff which is thread/process specific */
 typedef struct {
 #ifdef OPTIMIZE_TIMEOUTS
@@ -165,6 +170,7 @@ typedef struct {
     unsigned long my_bytes_served;
     unsigned long conn_bytes;
     unsigned short conn_count;
+    unsigned short life_status;    /* Either SB_WORKING or SB_IDLE_DIE */
     apr_time_t start_time;
     apr_time_t stop_time;
 #ifdef HAVE_TIMES
index 3cd30fe54b4be3c431f8916cb9123183adb2852b..17f07e888fe1a36fb0180c8bd1d19146ef8d5ef6 100644 (file)
@@ -466,6 +466,7 @@ static int status_handler(request_rec *r)
        ap_rputs("\"<B><code>D</code></B>\" DNS Lookup,<BR>\n", r);
        ap_rputs("\"<B><code>L</code></B>\" Logging, \n", r);
        ap_rputs("\"<B><code>G</code></B>\" Gracefully finishing, \n", r);
+        ap_rputs("\"<B><code>I</code></B>\" Idle cleanup of worker, \n", r);
        ap_rputs("\"<B><code>.</code></B>\" Open slot with no current process<P>\n", r);
        ap_rputs("<P>\n", r);
        if (!ap_extended_status) {
@@ -764,6 +765,7 @@ static void status_init(apr_pool_t *p, apr_pool_t *plog, apr_pool_t *ptemp, serv
     status_flags[SERVER_BUSY_LOG] = 'L';
     status_flags[SERVER_BUSY_DNS] = 'D';
     status_flags[SERVER_GRACEFUL] = 'G';
+    status_flags[SERVER_IDLE_KILL] = 'I';
 }
 
 static void register_hooks(apr_pool_t *p)
index 4e40eaa16efff59532ae714cab8fe04e8371be05..2546570d3b6578036f3c0f3473ef30ea71a10672 100644 (file)
@@ -232,6 +232,7 @@ static void clean_child_exit(int code)
     if (pchild) {
        apr_pool_destroy(pchild);
     }
+    ap_scoreboard_image->servers[my_child_num][0].life_status = SB_WORKING;
     chdir_for_gprof();
     exit(code);
 }
@@ -360,20 +361,18 @@ static void sig_coredump(int sig)
  * Connection structures and accounting...
  */
 
-static void just_die(int sig)
+static void please_die_gracefully(int sig)
 {
-    clean_child_exit(0);
-}
-
-static int volatile deferred_die;
-static int volatile usr1_just_die;
-
-static void usr1_handler(int sig)
-{
-    if (usr1_just_die) {
-       just_die(sig);
+    /* clean_child_exit(0); */
+    ap_scoreboard_image->servers[my_child_num][0].life_status = SB_IDLE_DIE;
+    if (sig == SIGHUP) {
+        (void) ap_update_child_status(AP_CHILD_THREAD_FROM_ID(my_child_num),
+                                      SERVER_GRACEFUL, (request_rec *) NULL);
+    }
+    else {
+        (void) ap_update_child_status(AP_CHILD_THREAD_FROM_ID(my_child_num),
+                                      SERVER_IDLE_KILL, (request_rec *) NULL);
     }
-    deferred_die = 1;
 }
 
 /* volatile just in case */
@@ -520,16 +519,16 @@ static apr_socket_t *csd;
 static int requests_this_child;
 static fd_set main_fds;
 
+#define I_AM_TO_SHUTDOWN()                                                   \
+(ap_scoreboard_image->servers[my_child_num][0].life_status != SB_WORKING)
+   
 int ap_graceful_stop_signalled(void)
 {
-    ap_sync_scoreboard_image();
-    if (deferred_die ||
-       ap_scoreboard_image->global.running_generation != ap_my_generation) {
-       return 1;
-    }
+    /* not ever called anymore... */
     return 0;
 }
 
+
 static void child_main(int child_num_arg)
 {
     ap_listen_rec *lr;
@@ -540,9 +539,9 @@ static void child_main(int child_num_arg)
     apr_status_t stat = APR_EINIT;
     int sockdes;
 
+    my_child_num = child_num_arg;
     ap_my_pid = getpid();
     csd = NULL;
-    my_child_num = child_num_arg;
     requests_this_child = 0;
     last_lr = NULL;
 
@@ -565,16 +564,16 @@ static void child_main(int child_num_arg)
 
     (void) ap_update_child_status(AP_CHILD_THREAD_FROM_ID(my_child_num), SERVER_READY, (request_rec *) NULL);
 
-    apr_signal(SIGHUP, just_die);
-    apr_signal(SIGTERM, just_die);
+    apr_signal(SIGHUP, please_die_gracefully);
+    apr_signal(SIGTERM, please_die_gracefully);
 
-    while (!ap_graceful_stop_signalled()) {
+    ap_sync_scoreboard_image();
+    while (!I_AM_TO_SHUTDOWN()) {
 
        /* Prepare to receive a SIGWINCH due to graceful restart so that
         * we can exit cleanly.
         */
-       usr1_just_die = 1;
-       apr_signal(SIGWINCH, usr1_handler);
+       apr_signal(SIGWINCH, please_die_gracefully);
 
        /*
         * (Re)initialize this child to a pre-connection state.
@@ -654,9 +653,9 @@ static void child_main(int child_num_arg)
            /* if we accept() something we don't want to die, so we have to
             * defer the exit
             */
-           usr1_just_die = 0;
            for (;;) {
-               if (deferred_die) {
+                ap_sync_scoreboard_image();
+               if (I_AM_TO_SHUTDOWN()) {
                    /* we didn't get a socket, and we were told to die */
                    clean_child_exit(0);
                }
@@ -763,10 +762,10 @@ static void child_main(int child_num_arg)
                }
            }
 
-           if (ap_graceful_stop_signalled()) {
+            ap_sync_scoreboard_image();
+           if (I_AM_TO_SHUTDOWN()) {
                clean_child_exit(0);
            }
-           usr1_just_die = 1;
        }
 
        SAFE_ACCEPT(accept_mutex_off());        /* unlock after "accept" */
@@ -791,12 +790,15 @@ static void child_main(int child_num_arg)
                          "(currently %d)", 
                          sockdes, FD_SETSIZE);
            apr_socket_close(csd);
+            ap_sync_scoreboard_image();
            continue;
         }
 
 #ifdef TPF
-       if (sockdes == 0)                   /* 0 is invalid socket for TPF */
-           continue;
+       if (sockdes == 0) {                  /* 0 is invalid socket for TPF */
+           ap_sync_scoreboard_image();
+            continue;
+        }
 #endif
 
        ap_sock_disable_nagle(csd);
@@ -807,6 +809,8 @@ static void child_main(int child_num_arg)
             ap_process_connection(current_conn);
             ap_lingering_close(current_conn);
         }
+        
+        ap_sync_scoreboard_image();
     }
     clean_child_exit(0);
 }
@@ -821,12 +825,13 @@ static int make_child(server_rec *s, int slot)
     }
 
     if (one_process) {
-       apr_signal(SIGHUP, just_die);
-       apr_signal(SIGINT, just_die);
+       apr_signal(SIGHUP, please_die_gracefully);
+       apr_signal(SIGINT, please_die_gracefully);
 #ifdef SIGQUIT
        apr_signal(SIGQUIT, SIG_DFL);
 #endif
-       apr_signal(SIGTERM, just_die);
+       apr_signal(SIGTERM, please_die_gracefully);
+        ap_scoreboard_image->servers[slot][0].life_status = SB_WORKING;
        child_main(slot);
     }
 
@@ -870,13 +875,14 @@ static int make_child(server_rec *s, int slot)
        }
 #endif
        RAISE_SIGSTOP(MAKE_CHILD);
-       /* Disable the restart signal handlers and enable the just_die stuff.
+       /* Disable the restart signal handlers and enable the please_die_gracefully stuff.
         * Note that since restart() just notes that a restart has been
         * requested there's no race condition here.
         */
-       apr_signal(SIGHUP, just_die);
-       apr_signal(SIGWINCH, just_die);
-       apr_signal(SIGTERM, just_die);
+       apr_signal(SIGHUP, please_die_gracefully);
+       apr_signal(SIGWINCH, please_die_gracefully);
+       apr_signal(SIGTERM, please_die_gracefully);
+        ap_scoreboard_image->servers[slot][0].life_status = SB_WORKING;
        child_main(slot);
     }
 
@@ -1066,6 +1072,7 @@ static int setup_listeners(server_rec *s)
 
 int ap_mpm_run(apr_pool_t *_pconf, apr_pool_t *plog, server_rec *s)
 {
+    int index;
     int remaining_children_to_start;
 
     pconf = _pconf;
@@ -1236,11 +1243,12 @@ int ap_mpm_run(apr_pool_t *_pconf, apr_pool_t *plog, server_rec *s)
     ++ap_my_generation;
     ap_scoreboard_image->global.running_generation = ap_my_generation;
     update_scoreboard_global();
+    
+    for (index = 0; index < ap_daemons_limit; ++index) {
+        ap_scoreboard_image->servers[index][0].life_status = SB_IDLE_DIE;
+    }
 
     if (is_graceful) {
-#ifndef SCOREBOARD_FILE
-       int i;
-#endif
        ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_NOTICE, 0, ap_server_conf,
                    "SIGWINCH received.  Doing graceful restart");
 
@@ -1255,9 +1263,9 @@ int ap_mpm_run(apr_pool_t *_pconf, apr_pool_t *plog, server_rec *s)
            * corruption too easily.
            */
        ap_sync_scoreboard_image();
-       for (i = 0; i < ap_daemons_limit; ++i) {
-           if (ap_scoreboard_image->servers[i][0].status != SERVER_DEAD) {
-               ap_scoreboard_image->servers[i][0].status = SERVER_GRACEFUL;
+       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;
            }
        }
 #endif
index d9ecdb00d8a1f4969b4e457e2941aeb0b9a76b33..784aee3eba79c73519f4823ab9f38006e098ad12 100644 (file)
@@ -126,9 +126,9 @@ void ap_reclaim_child_processes(int terminate)
             switch (tries) {
             case 1:     /*  16ms */
             case 2:     /*  82ms */
-                break;
             case 3:     /* 344ms */
             case 4:     /*  16ms */
+                break;
             case 5:     /*  82ms */
             case 6:     /* 344ms */
             case 7:     /* 1.4sec */