From d9781f173416a236c4da1e4b3c756c831a69eb5f Mon Sep 17 00:00:00 2001 From: Stefan Fritsch Date: Sun, 10 Apr 2016 22:53:42 +0000 Subject: [PATCH] Exit threads early during shutdown, part 2 Follow up to r1738466: During graceful shutdown, when the listener thread is closing a connection, it needs to wake up a worker thread so that it may terminate. git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1738486 13f79535-47bb-0310-9956-ffa450edef68 --- server/mpm/event/event.c | 6 ++++++ server/mpm/event/fdqueue.c | 16 ++++++++++++---- server/mpm/event/fdqueue.h | 1 + 3 files changed, 19 insertions(+), 4 deletions(-) diff --git a/server/mpm/event/event.c b/server/mpm/event/event.c index a3a709862e..4c4853f856 100644 --- a/server/mpm/event/event.c +++ b/server/mpm/event/event.c @@ -950,6 +950,8 @@ static int start_lingering_close_nonblocking(event_conn_state_t *cs) || apr_socket_shutdown(csd, APR_SHUTDOWN_WRITE) != APR_SUCCESS) { apr_socket_close(csd); ap_push_pool(worker_queue_info, cs->p); + if (dying) + ap_queue_interrupt_one(worker_queue); return 0; } return start_lingering_close_common(cs, 0); @@ -973,6 +975,8 @@ static int stop_lingering_close(event_conn_state_t *cs) AP_DEBUG_ASSERT(0); } ap_push_pool(worker_queue_info, cs->p); + if (dying) + ap_queue_interrupt_one(worker_queue); return 0; } @@ -1645,6 +1649,8 @@ static void process_lingering_close(event_conn_state_t *cs, const apr_pollfd_t * TO_QUEUE_ELEM_INIT(cs); ap_push_pool(worker_queue_info, cs->p); + if (dying) + ap_queue_interrupt_one(worker_queue); } /* call 'func' for all elements of 'q' with timeout less than 'timeout_time'. diff --git a/server/mpm/event/fdqueue.c b/server/mpm/event/fdqueue.c index 75b79047b2..7775a157d0 100644 --- a/server/mpm/event/fdqueue.c +++ b/server/mpm/event/fdqueue.c @@ -487,7 +487,7 @@ apr_status_t ap_queue_pop_something(fd_queue_t * queue, apr_socket_t ** sd, return rv; } -static apr_status_t queue_interrupt_all(fd_queue_t *queue, int term) +static apr_status_t queue_interrupt(fd_queue_t *queue, int all, int term) { apr_status_t rv; @@ -501,16 +501,24 @@ static apr_status_t queue_interrupt_all(fd_queue_t *queue, int term) if (term) { queue->terminated = 1; } - apr_thread_cond_broadcast(queue->not_empty); + if (all) + apr_thread_cond_broadcast(queue->not_empty); + else + apr_thread_cond_signal(queue->not_empty); return apr_thread_mutex_unlock(queue->one_big_mutex); } apr_status_t ap_queue_interrupt_all(fd_queue_t * queue) { - return queue_interrupt_all(queue, 0); + return queue_interrupt(queue, 1, 0); +} + +apr_status_t ap_queue_interrupt_one(fd_queue_t * queue) +{ + return queue_interrupt(queue, 0, 0); } apr_status_t ap_queue_term(fd_queue_t * queue) { - return queue_interrupt_all(queue, 1); + return queue_interrupt(queue, 1, 1); } diff --git a/server/mpm/event/fdqueue.h b/server/mpm/event/fdqueue.h index 00059d3563..df54217387 100644 --- a/server/mpm/event/fdqueue.h +++ b/server/mpm/event/fdqueue.h @@ -101,6 +101,7 @@ apr_status_t ap_queue_pop_something(fd_queue_t * queue, apr_socket_t ** sd, event_conn_state_t ** ecs, apr_pool_t ** p, timer_event_t ** te); apr_status_t ap_queue_interrupt_all(fd_queue_t * queue); +apr_status_t ap_queue_interrupt_one(fd_queue_t * queue); apr_status_t ap_queue_term(fd_queue_t * queue); #endif /* FDQUEUE_H */ -- 2.40.0