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 ||