Index: trunk/server/mpm/experimental/event/event.c =================================================================== --- trunk/server/mpm/experimental/event/event.c (revision 582993) +++ trunk/server/mpm/experimental/event/event.c (working copy) @@ -55,6 +55,7 @@ #include "apr_poll.h" #include "apr_ring.h" #include "apr_queue.h" +#include "apr_atomic.h" #define APR_WANT_STRFUNC #include "apr_want.h" @@ -396,7 +397,13 @@ static int volatile is_graceful; static volatile int child_fatal; ap_generation_t volatile ap_my_generation = 0; +static volatile apr_uint32_t connection_count = 0; +static apr_status_t decrement_connection_count(void *dummy){ + apr_atomic_dec32(&connection_count); + return APR_SUCCESS; +} + /* * ap_start_shutdown() and ap_start_restart(), below, are a first stab at * functions to initiate shutdown or restart without relying on signals. @@ -577,6 +584,8 @@ cs->bucket_alloc = apr_bucket_alloc_create(p); c = ap_run_create_connection(p, ap_server_conf, sock, conn_id, sbh, cs->bucket_alloc); + apr_atomic_inc32(&connection_count); + apr_pool_cleanup_register(c->pool, NULL, decrement_connection_count, apr_pool_cleanup_null); cs->c = c; c->cs = cs; cs->p = p; @@ -885,6 +894,29 @@ } } +static void close_listeners(int process_slot, int *closed){ + if(!*closed){ + ap_listen_rec *lr; + int i; + for (lr = ap_listeners; lr != NULL; lr = lr->next) { + apr_pollfd_t *pfd = apr_pcalloc(pchild, sizeof(*pfd)); + pfd->desc_type = APR_POLL_SOCKET; + pfd->desc.s = lr->sd; + apr_pollset_remove(event_pollset, pfd); + } + ap_close_listeners(); + *closed = 1; + dying = 1; + ap_scoreboard_image->parent[process_slot].quiescing = 1; + for(i = 0; i < ap_threads_per_child; ++i){ + ap_update_child_status_from_indexes(process_slot, i, + SERVER_DEAD, NULL); + } + /* wake up the main thread */ + kill(ap_my_pid, SIGTERM); + } +} + static void * APR_THREAD_FUNC listener_thread(apr_thread_t * thd, void *dummy) { apr_status_t rc; @@ -902,6 +934,7 @@ apr_interval_time_t timeout_interval; apr_time_t timeout_time; listener_poll_type *pt; + int closed = 0; free(ti); @@ -935,7 +968,12 @@ unblock_signal(LISTENER_SIGNAL); apr_signal(LISTENER_SIGNAL, dummy_signal_handler); - while (!listener_may_exit) { + for(;;) { + if(listener_may_exit){ + close_listeners(process_slot, &closed); + if(terminate_mode == ST_UNGRACEFUL || apr_atomic_read32(&connection_count) == 0) + break; + } if (requests_this_child <= 0) { check_infinite_requests(); @@ -956,8 +994,11 @@ } } - if (listener_may_exit) - break; + if(listener_may_exit){ + close_listeners(process_slot, &closed); + if(terminate_mode == ST_UNGRACEFUL || apr_atomic_read32(&connection_count) == 0) + break; + } while (num && get_worker(&have_idle_worker)) { pt = (listener_poll_type *) out_pfd->client_data; @@ -1128,14 +1169,9 @@ } /* listener main loop */ - ap_close_listeners(); + close_listeners(process_slot, &closed); ap_queue_term(worker_queue); - dying = 1; - ap_scoreboard_image->parent[process_slot].quiescing = 1; - /* wake up the main thread */ - kill(ap_my_pid, SIGTERM); - apr_thread_exit(thd, APR_SUCCESS); return NULL; } @@ -1180,7 +1216,7 @@ } ap_update_child_status_from_indexes(process_slot, thread_slot, - SERVER_READY, NULL); + dying ? SERVER_DEAD : SERVER_READY, NULL); worker_pop: if (workers_may_exit) { break; @@ -1402,21 +1438,15 @@ */ iter = 0; - while (iter < 10 && -#ifdef HAVE_PTHREAD_KILL - pthread_kill(*listener_os_thread, 0) -#else - kill(ap_my_pid, 0) -#endif - == 0) { - /* listener not dead yet */ + while (iter < 10 && !dying) { + /* listener has not stopped accepting yet */ apr_sleep(apr_time_make(0, 500000)); wakeup_listener(); ++iter; } if (iter >= 10) { ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, ap_server_conf, - "the listener thread didn't exit"); + "the listener thread didn't stop accepting"); } else { rv = apr_thread_join(&thread_rv, listener);