Changes with Apache 2.0.34-dev
+ *) Fix some restart/terminate problems in the worker MPM. Don't
+ drop connections during graceful restart. [Jeff Trawick]
+
*) Change the header merging behaviour in proxy, as some headers
(like Set-Cookie) cannot be unmerged due to stray commas in
dates. [Graham Leggett]
return rv;
}
+ AP_DEBUG_ASSERT(!queue->terminated);
+
while (ap_queue_full(queue)) {
apr_thread_cond_wait(queue->not_full, queue->one_big_mutex);
}
/* Keep waiting until we wake up and find that the queue is not empty. */
if (ap_queue_empty(queue)) {
- apr_thread_cond_wait(queue->not_empty, queue->one_big_mutex);
+ if (!queue->terminated) {
+ apr_thread_cond_wait(queue->not_empty, queue->one_big_mutex);
+ }
/* If we wake up and it's still empty, then we were interrupted */
if (ap_queue_empty(queue)) {
if ((rv = apr_thread_mutex_unlock(queue->one_big_mutex)) != APR_SUCCESS) {
return rv;
}
- return APR_EINTR;
+ if (queue->terminated) {
+ return APR_EOF; /* no more elements ever again */
+ }
+ else {
+ return APR_EINTR;
+ }
}
}
return APR_SUCCESS;
}
+apr_status_t ap_queue_term(fd_queue_t *queue)
+{
+ apr_status_t rv;
+
+ if ((rv = apr_thread_mutex_lock(queue->one_big_mutex)) != APR_SUCCESS) {
+ return rv;
+ }
+ /* we must hold one_big_mutex when setting this... otherwise,
+ * we could end up setting it and waking everybody up just after a
+ * would-be popper checks it but right before they block
+ */
+ queue->terminated = 1;
+ if ((rv = apr_thread_mutex_unlock(queue->one_big_mutex)) != APR_SUCCESS) {
+ return rv;
+ }
+ return ap_queue_interrupt_all(queue);
+}
apr_thread_cond_t *not_full;
apr_pool_t **recycled_pools;
int num_recycled;
+ int terminated;
};
typedef struct fd_queue_t fd_queue_t;
apr_status_t ap_queue_pop(fd_queue_t *queue, apr_socket_t **sd, apr_pool_t **p,
apr_pool_t *recycled_pool);
apr_status_t ap_queue_interrupt_all(fd_queue_t *queue);
+apr_status_t ap_queue_term(fd_queue_t *queue);
#endif /* FDQUEUE_H */
static void signal_threads(int mode)
{
+ static int prev_mode = 0;
+
+ if (prev_mode == mode) {
+ return;
+ }
+ prev_mode = mode;
+
/* in case we weren't called from the listener thread, wake up the
* listener thread
*/
wakeup_listener();
+ /* for ungraceful termination, let the workers exit now;
+ * for graceful termination, the listener thread will notify the
+ * workers to exit once it has stopped accepting new connections
+ */
+ if (mode == ST_UNGRACEFUL) {
+ workers_may_exit = 1;
+ ap_queue_interrupt_all(worker_queue);
+ }
+
/* XXX: This will happen naturally on a graceful, and we don't care
* otherwise.
ap_queue_signal_all_wakeup(worker_queue); */
-
- workers_may_exit = 1;
- ap_queue_interrupt_all(worker_queue);
}
AP_DECLARE(apr_status_t) ap_mpm_query(int query_code, int *result)
ap_update_child_status_from_indexes(process_slot, thread_slot,
(dying) ? SERVER_DEAD : SERVER_GRACEFUL,
(request_rec *) NULL);
+ ap_queue_term(worker_queue);
dying = 1;
ap_scoreboard_image->parent[process_slot].quiescing = 1;
kill(ap_my_pid, SIGTERM);
last_ptrans = NULL;
if (rv != APR_SUCCESS) {
+ /* We get APR_EOF during a graceful shutdown once all the connections
+ * accepted by this server process have been handled.
+ */
+ if (rv == APR_EOF) {
+ break;
+ }
/* We get APR_EINTR whenever ap_queue_pop() has been interrupted
* from an explicit call to ap_queue_interrupt_all(). This allows
* us to unblock threads stuck in ap_queue_pop() when a shutdown