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