static int changed_limit_at_restart;
static int dying = 0;
static int workers_may_exit = 0;
+static int start_thread_may_exit = 0;
+static int listener_may_exit = 0;
static int requests_this_child;
static int num_listensocks = 0;
static int resource_shortage = 0;
static void wakeup_listener(void)
{
+ listener_may_exit = 1;
/*
* we should just be able to "kill(ap_my_pid, LISTENER_SIGNAL)" and wake
* up the listener thread since it is the only thread with SIGHUP
pthread_kill(*listener_os_thread, LISTENER_SIGNAL);
}
-static void signal_workers(void)
-{
- workers_may_exit = 1;
+#define ST_GRACEFUL 1
+#define ST_UNGRACEFUL 2
+static void signal_threads(int mode)
+{
/* in case we weren't called from the listener thread, wake up the
* listener thread
*/
/* 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);
}
* maybe it should be ap_mpm_process_exiting?
*/
{
- return workers_may_exit;
+ /* note: for a graceful termination, listener_may_exit will be set before
+ * workers_may_exit, so check listener_may_exit
+ */
+ return listener_may_exit;
}
/*****************************************************************
static void check_infinite_requests(void)
{
if (ap_max_requests_per_child) {
- signal_workers();
+ signal_threads(ST_GRACEFUL);
}
else {
/* wow! if you're executing this code, you may have set a record.
if (requests_this_child <= 0) {
check_infinite_requests();
}
- if (workers_may_exit) break;
+ if (listener_may_exit) break;
if ((rv = SAFE_ACCEPT(apr_proc_mutex_lock(accept_mutex)))
!= APR_SUCCESS) {
int level = APLOG_EMERG;
- if (workers_may_exit) {
+ if (listener_may_exit) {
break;
}
if (ap_scoreboard_image->parent[process_slot].generation !=
ap_log_error(APLOG_MARK, level, rv, ap_server_conf,
"apr_proc_mutex_lock failed. Attempting to shutdown "
"process gracefully.");
- signal_workers();
+ signal_threads(ST_GRACEFUL);
break; /* skip the lock release */
}
lr = ap_listeners;
}
else {
- while (!workers_may_exit) {
+ while (!listener_may_exit) {
apr_status_t ret;
apr_int16_t event;
* circumstances. Let's try exiting gracefully, for now. */
ap_log_error(APLOG_MARK, APLOG_ERR, ret, (const server_rec *)
ap_server_conf, "apr_poll: (listen)");
- signal_workers();
+ signal_threads(ST_GRACEFUL);
}
- if (workers_may_exit) break;
+ if (listener_may_exit) break;
/* find a listener */
lr = last_lr;
}
}
got_fd:
- if (!workers_may_exit) {
+ if (!listener_may_exit) {
/* create a new transaction pool for each accepted socket */
if (recycled_pool == NULL) {
apr_allocator_t *allocator;
if (rv == APR_EGENERAL) {
/* E[NM]FILE, ENOMEM, etc */
resource_shortage = 1;
- signal_workers();
+ signal_threads(ST_GRACEFUL);
}
if ((rv = SAFE_ACCEPT(apr_proc_mutex_unlock(accept_mutex)))
!= APR_SUCCESS) {
int level = APLOG_EMERG;
- if (workers_may_exit) {
+ if (listener_may_exit) {
break;
}
if (ap_scoreboard_image->parent[process_slot].generation !=
ap_log_error(APLOG_MARK, level, rv, ap_server_conf,
"apr_proc_mutex_unlock failed. Attempting to "
"shutdown process gracefully.");
- signal_workers();
+ signal_threads(ST_GRACEFUL);
}
if (csd != NULL) {
rv = ap_queue_push(worker_queue, csd, ptrans,
ap_log_error(APLOG_MARK, APLOG_EMERG, rv, ap_server_conf,
"apr_proc_mutex_unlock failed. Attempting to "
"shutdown process gracefully.");
- signal_workers();
+ signal_threads(ST_GRACEFUL);
}
break;
}
}
threads_created++;
}
- if (workers_may_exit || threads_created == ap_threads_per_child) {
+ if (start_thread_may_exit || threads_created == ap_threads_per_child) {
break;
}
/* wait for previous generation to clean up an entry */
/* 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
- * workers_may_exit flag is clear and the time it enters a
+ * 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
*/
{
apr_status_t rv, thread_rv;
- workers_may_exit = 1; /* start thread may not want to exit until this
- * is set
- */
+ start_thread_may_exit = 1; /* tell it to give up in case it is still
+ * trying to take over slots from a
+ * previous generation
+ */
rv = apr_thread_join(&thread_rv, start_thread_id);
if (rv != APR_SUCCESS) {
ap_log_error(APLOG_MARK, APLOG_CRIT, rv, ap_server_conf,
if (one_process) {
/* Block until we get a terminating signal. */
apr_signal_thread(check_signal);
- /* make sure the start thread has finished; signal_workers()
+ /* make sure the start thread has finished; signal_threads()
* and join_workers() depend on that
*/
/* XXX join_start_thread() won't be awakened if one of our
* shutdown this child
*/
join_start_thread(start_thread_id);
- signal_workers(); /* helps us terminate a little more quickly when
- * the dispatch of the signal thread
+ signal_threads(ST_UNGRACEFUL); /* helps us terminate a little more
+ * quickly than the dispatch of the signal thread
* beats the Pipe of Death and the browsers
*/
/* A terminating signal was received. Now join each of the
rv = ap_mpm_pod_check(pod);
if (rv == AP_GRACEFUL || rv == AP_RESTART) {
/* make sure the start thread has finished;
- * signal_workers() and join_workers depend on that
+ * signal_threads() and join_workers depend on that
*/
join_start_thread(start_thread_id);
- signal_workers();
+ signal_threads(rv == AP_GRACEFUL ? ST_GRACEFUL : ST_UNGRACEFUL);
break;
}
}