On 01/06/2009 07:10 PM, William A. Rowe, Jr. wrote:
> Would folks comment on Nathan's, Joe's and Stefan's work on
> 
> https://issues.apache.org/bugzilla/show_bug.cgi?id=42829
> 
> and offer any comments on why this patch;
> 
> https://issues.apache.org/bugzilla/attachment.cgi?id=22822
> 
> should not be applied to trunk/ and branches/2.2.x/ in time for
> the next releases?

@@ -573,6 +588,11 @@ static void child_main(int child_num_arg
                 apr_int32_t numdesc;
                 const apr_pollfd_t *pdesc;

+                if (die_now) {
+                    status = !APR_SUCCESS;
+                    goto unlock;
+                }
+

Hm, what happens if we get the signal exactly here?
Then stop_listening only set die_now to 1. So we reenter the poll and stay in
until we get a new request to OUR process on one of the listeners.
Is this the desired behaviour?

                 /* timeout == -1 == wait forever */
                 status = apr_pollset_poll(pollset, -1, &numdesc, &pdesc);
                 if (status != APR_SUCCESS) {

How about this one instead:

Index: server/mpm/prefork/prefork.c
===================================================================
--- server/mpm/prefork/prefork.c        (Revision 731601)
+++ server/mpm/prefork/prefork.c        (Arbeitskopie)
@@ -99,6 +99,8 @@
 static int mpm_state = AP_MPMQ_STARTING;
 static ap_pod_t *pod;

+static int dummy_listener;
+
 /*
  * The max child slot ever assigned, preserved across restarts.  Necessary
  * to deal with MaxClients changes across AP_SIG_GRACEFUL restarts.  We
@@ -136,6 +138,8 @@
 #endif /* TPF */

 static volatile int die_now = 0;
+static volatile int listeners_closed = 0;
+static int close_connection = 1;

 #ifdef GPROF
 /*
@@ -304,8 +308,19 @@

 static void stop_listening(int sig)
 {
-    ap_close_listeners();
+    if (close_connection && !listeners_closed) {
+        ap_listen_rec *lr;

+        for (lr = ap_listeners; lr; lr = lr->next) {
+            apr_os_sock_t fd;
+
+            apr_os_sock_get(&fd, lr->sd);
+
+            dup2(dummy_listener, fd);
+        }
+        listeners_closed = 1;
+    }
+
     /* For a graceful stop, we want the child to exit when done */
     die_now = 1;
 }
@@ -533,6 +548,7 @@
         if (num_listensocks == 1) {
             /* There is only one listener record, so refer to that one. */
             lr = ap_listeners;
+            close_connection = 0;
         }
         else {
             /* multiple listening sockets - need to poll */
@@ -540,8 +556,14 @@
                 apr_int32_t numdesc;
                 const apr_pollfd_t *pdesc;

+                if (die_now) {
+                    status = !APR_SUCCESS;
+                    goto unlock;
+                }
+
                 /* timeout == -1 == wait forever */
                 status = apr_pollset_poll(pollset, -1, &numdesc, &pdesc);
+                close_connection = 0;
                 if (status != APR_SUCCESS) {
                     if (APR_STATUS_IS_EINTR(status)) {
                         if (one_process && shutdown_pending) {
@@ -595,8 +617,15 @@
         /* if we accept() something we don't want to die, so we have to
          * defer the exit
          */
-        status = lr->accept_func(&csd, lr, ptrans);
+        if (!die_now) {
+            status = lr->accept_func(&csd, lr, ptrans);
+        }
+        else {
+            status = !APR_SUCCESS;
+        }

+    unlock:
+        close_connection = 1;
         SAFE_ACCEPT(accept_mutex_off());      /* unlock after "accept" */

         if (status == APR_EGENERAL) {
@@ -612,6 +641,11 @@
          * socket options, file descriptors, and read/write buffers.
          */

+        if (die_now && !listeners_closed) {
+            ap_close_listeners();
+            listeners_closed = 1;
+        }
+
         current_conn = ap_run_create_connection(ptrans, ap_server_conf, csd, 
my_child_num, sbh, bucket_alloc);
         if (current_conn) {
             ap_process_connection(current_conn, csd);
@@ -890,6 +924,17 @@
         mpm_state = AP_MPMQ_STOPPING;
         return 1;
     }
+
+    if (dummy_listener == 0) {
+        dummy_listener = socket(AF_INET, SOCK_STREAM, 0);
+        if (dummy_listener < 0) {
+            rv = errno;
+            ap_log_error(APLOG_MARK, APLOG_EMERG, rv, s,
+                         "Couldn't create dummy listener socket");
+            mpm_state = AP_MPMQ_STOPPING;
+            return 1;
+        }
+    }

 #if APR_USE_SYSVSEM_SERIALIZE
     if (ap_accept_lock_mech == APR_LOCK_DEFAULT ||



Regards

Rüdiger

Index: server/mpm/prefork/prefork.c
===================================================================
--- server/mpm/prefork/prefork.c	(Revision 731601)
+++ server/mpm/prefork/prefork.c	(Arbeitskopie)
@@ -99,6 +99,8 @@
 static int mpm_state = AP_MPMQ_STARTING;
 static ap_pod_t *pod;
 
+static int dummy_listener;
+
 /*
  * The max child slot ever assigned, preserved across restarts.  Necessary
  * to deal with MaxClients changes across AP_SIG_GRACEFUL restarts.  We
@@ -136,6 +138,8 @@
 #endif /* TPF */
 
 static volatile int die_now = 0;
+static volatile int listeners_closed = 0;
+static int close_connection = 1;
 
 #ifdef GPROF
 /*
@@ -304,8 +308,19 @@
 
 static void stop_listening(int sig)
 {
-    ap_close_listeners();
+    if (close_connection && !listeners_closed) {
+        ap_listen_rec *lr;
 
+        for (lr = ap_listeners; lr; lr = lr->next) {
+            apr_os_sock_t fd;
+
+            apr_os_sock_get(&fd, lr->sd);
+
+            dup2(dummy_listener, fd);
+        }
+        listeners_closed = 1;
+    }
+
     /* For a graceful stop, we want the child to exit when done */
     die_now = 1;
 }
@@ -533,6 +548,7 @@
         if (num_listensocks == 1) {
             /* There is only one listener record, so refer to that one. */
             lr = ap_listeners;
+            close_connection = 0;
         }
         else {
             /* multiple listening sockets - need to poll */
@@ -540,8 +556,14 @@
                 apr_int32_t numdesc;
                 const apr_pollfd_t *pdesc;
 
+                if (die_now) {
+                    status = !APR_SUCCESS;
+                    goto unlock;
+                }
+
                 /* timeout == -1 == wait forever */
                 status = apr_pollset_poll(pollset, -1, &numdesc, &pdesc);
+                close_connection = 0;
                 if (status != APR_SUCCESS) {
                     if (APR_STATUS_IS_EINTR(status)) {
                         if (one_process && shutdown_pending) {
@@ -595,8 +617,15 @@
         /* if we accept() something we don't want to die, so we have to
          * defer the exit
          */
-        status = lr->accept_func(&csd, lr, ptrans);
+        if (!die_now) {
+            status = lr->accept_func(&csd, lr, ptrans);
+        }
+        else {
+            status = !APR_SUCCESS;
+        }
 
+    unlock:
+        close_connection = 1;
         SAFE_ACCEPT(accept_mutex_off());      /* unlock after "accept" */
 
         if (status == APR_EGENERAL) {
@@ -612,6 +641,11 @@
          * socket options, file descriptors, and read/write buffers.
          */
 
+        if (die_now && !listeners_closed) {
+            ap_close_listeners();
+            listeners_closed = 1;
+        }
+
         current_conn = ap_run_create_connection(ptrans, ap_server_conf, csd, my_child_num, sbh, bucket_alloc);
         if (current_conn) {
             ap_process_connection(current_conn, csd);
@@ -890,6 +924,17 @@
         mpm_state = AP_MPMQ_STOPPING;
         return 1;
     }
+    
+    if (dummy_listener == 0) {
+        dummy_listener = socket(AF_INET, SOCK_STREAM, 0);
+        if (dummy_listener < 0) {
+            rv = errno;
+            ap_log_error(APLOG_MARK, APLOG_EMERG, rv, s,
+                         "Couldn't create dummy listener socket");
+            mpm_state = AP_MPMQ_STOPPING;
+            return 1;
+        }
+    }        
 
 #if APR_USE_SYSVSEM_SERIALIZE
     if (ap_accept_lock_mech == APR_LOCK_DEFAULT ||

Reply via email to