Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 44 additions & 2 deletions server/mpm/event/event.c
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,9 @@ static fd_queue_info_t *worker_queue_info;

static apr_thread_mutex_t *timeout_mutex;

static int idle_termination_timeout = -1; /* never terminate by default */
static int idle_termination_remaining;

module AP_MODULE_DECLARE_DATA mpm_event_module;

/* forward declare */
Expand Down Expand Up @@ -444,6 +447,8 @@ typedef struct event_retained_data {
*/
int *idle_spawn_rate;
int hold_off_on_exponential_spawning;

int idle_timeout; /* did we time out? */
} event_retained_data;
static event_retained_data *retained;

Expand Down Expand Up @@ -3242,6 +3247,7 @@ static void perform_idle_server_maintenance(int child_bucket,
{
int num_buckets = retained->mpm->num_buckets;
int idle_thread_count = 0;
int total_thread_count = 0;
process_score *ps;
int free_length = 0;
int free_slots[MAX_SPAWN_RATE];
Expand Down Expand Up @@ -3292,6 +3298,7 @@ static void perform_idle_server_maintenance(int child_bucket,
if (status >= SERVER_READY && status < SERVER_GRACEFUL) {
++child_threads_active;
}
++total_thread_count;
}
active_thread_count += child_threads_active;
if (child_threads_active == threads_per_child) {
Expand Down Expand Up @@ -3338,6 +3345,21 @@ static void perform_idle_server_maintenance(int child_bucket,
&& retained->total_daemons <= retained->max_daemon_used
&& retained->max_daemon_used <= server_limit);

if (idle_termination_timeout >= 0) {
if (idle_thread_count == total_thread_count) {
/* we are completely idle, decrease and check the timer */
if (--idle_termination_remaining < 0) {
/* the termination timeout has expired, inform us we want to terminate immediately */
retained->mpm->shutdown_pending = 1;
retained->mpm->is_ungraceful = 1;
retained->idle_timeout = 1;
}
} else {
/* not idle, reset the timer */
idle_termination_remaining = idle_termination_timeout;
}
}

if (idle_thread_count > max_spare_threads / num_buckets) {
/*
* Child processes that we ask to shut down won't die immediately
Expand Down Expand Up @@ -3783,8 +3805,15 @@ static int event_run(apr_pool_t * _pconf, apr_pool_t * plog, server_rec * s)
if (!child_fatal) {
/* cleanup pid file on normal shutdown */
ap_remove_pid(pconf, ap_pid_fname);
ap_log_error(APLOG_MARK, APLOG_NOTICE, 0,
ap_server_conf, APLOGNO(00491) "caught SIGTERM, shutting down");

/* log message depends on if we are terminating by signal or by idle timeout */
if (!retained->idle_timeout) {
ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, ap_server_conf, APLOGNO(00491)
"caught SIGTERM, shutting down");
} else {
ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, ap_server_conf, APLOGNO(00491)
"idle timeout reached, shutting down");
}
}

return DONE;
Expand Down Expand Up @@ -4481,6 +4510,17 @@ static const char *set_worker_factor(cmd_parms * cmd, void *dummy,
return NULL;
}

static const char *set_idle_termination_timeout (cmd_parms *cmd, void *dummy, const char *arg)
{
const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
if (err != NULL) {
return err;
}

idle_termination_timeout = atoi(arg);
idle_termination_remaining = idle_termination_timeout;
return NULL;
}

static const command_rec event_cmds[] = {
LISTEN_COMMANDS,
Expand All @@ -4504,6 +4544,8 @@ static const command_rec event_cmds[] = {
AP_INIT_TAKE1("AsyncRequestWorkerFactor", set_worker_factor, NULL, RSRC_CONF,
"How many additional connects will be accepted per idle "
"worker thread"),
AP_INIT_TAKE1("IdleTerminationTimeout", set_idle_termination_timeout, NULL, RSRC_CONF,
"Number of seconds to terminate in when the server is idle"),
AP_GRACEFUL_SHUTDOWN_TIMEOUT_COMMAND,
{NULL}
};
Expand Down
Loading