Index: trunk/server/mpm/experimental/event/event.c =================================================================== --- trunk/server/mpm/experimental/event/event.c (revision 582289) +++ 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,6 +397,7 @@ 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; /* * ap_start_shutdown() and ap_start_restart(), below, are a first stab at @@ -569,6 +571,8 @@ ap_create_sb_handle(&sbh, p, my_child_num, my_thread_num); if (cs == NULL) { /* This is a new connection */ + + apr_atomic_inc32(&connection_count); cs = apr_pcalloc(p, sizeof(conn_state_t)); @@ -596,6 +600,7 @@ ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, ap_server_conf, "process_socket: connection aborted"); c->aborted = 1; + apr_atomic_dec32(&connection_count); } /** @@ -687,6 +692,7 @@ ap_lingering_close(c); apr_pool_clear(p); ap_push_pool(worker_queue_info, p); + apr_atomic_dec32(&connection_count); return 1; } else if (cs->state == CONN_STATE_CHECK_REQUEST_LINE_READABLE) { @@ -885,6 +891,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 +931,7 @@ apr_interval_time_t timeout_interval; apr_time_t timeout_time; listener_poll_type *pt; + int closed = 0; free(ti); @@ -935,7 +965,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 +991,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 +1166,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 +1213,7 @@ } ap_update_child_status_from_indexes(process_slot, thread_slot, - SERVER_READY, NULL); + dying ? SERVER_GRACEFUL : SERVER_READY, NULL); worker_pop: if (workers_may_exit) { break; @@ -1385,48 +1418,11 @@ return NULL; } -static void join_workers(apr_thread_t * listener, apr_thread_t ** threads) +static void join_workers(apr_thread_t ** threads) { int i; apr_status_t rv, thread_rv; - if (listener) { - int iter; - - /* deal with a rare timing window which affects waking up the - * listener thread... if the signal sent to the listener thread - * is delivered between the time it verifies that the - * listener_may_exit flag is clear and the time it enters a - * blocking syscall, the signal didn't do any good... work around - * that by sleeping briefly and sending it again - */ - - 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 */ - 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"); - } - else { - rv = apr_thread_join(&thread_rv, listener); - if (rv != APR_SUCCESS) { - ap_log_error(APLOG_MARK, APLOG_CRIT, rv, ap_server_conf, - "apr_thread_join: unable to join listener thread"); - } - } - } - for (i = 0; i < ap_threads_per_child; i++) { if (threads[i]) { /* if we ever created this thread */ rv = apr_thread_join(&thread_rv, threads[i]); @@ -1565,7 +1561,7 @@ * If the worker hasn't exited, then this blocks until * they have (then cleans up). */ - join_workers(ts->listener, threads); + join_workers(threads); } else { /* !one_process */ /* remove SIGTERM from the set of blocked signals... if one of @@ -1606,7 +1602,7 @@ * If the worker hasn't exited, then this blocks until * they have (then cleans up). */ - join_workers(ts->listener, threads); + join_workers(threads); } free(threads);