@@ -199,6 +199,9 @@ static fd_queue_info_t *worker_queue_info;
199199
200200static apr_thread_mutex_t * timeout_mutex ;
201201
202+ static int idle_termination_timeout = -1 ; /* never terminate by default */
203+ static int idle_termination_remaining ;
204+
202205module AP_MODULE_DECLARE_DATA mpm_event_module ;
203206
204207/* forward declare */
@@ -444,6 +447,8 @@ typedef struct event_retained_data {
444447 */
445448 int * idle_spawn_rate ;
446449 int hold_off_on_exponential_spawning ;
450+
451+ int idle_timeout ; /* did we time out? */
447452} event_retained_data ;
448453static event_retained_data * retained ;
449454
@@ -3242,6 +3247,7 @@ static void perform_idle_server_maintenance(int child_bucket,
32423247{
32433248 int num_buckets = retained -> mpm -> num_buckets ;
32443249 int idle_thread_count = 0 ;
3250+ int total_thread_count = 0 ;
32453251 process_score * ps ;
32463252 int free_length = 0 ;
32473253 int free_slots [MAX_SPAWN_RATE ];
@@ -3292,6 +3298,7 @@ static void perform_idle_server_maintenance(int child_bucket,
32923298 if (status >= SERVER_READY && status < SERVER_GRACEFUL ) {
32933299 ++ child_threads_active ;
32943300 }
3301+ ++ total_thread_count ;
32953302 }
32963303 active_thread_count += child_threads_active ;
32973304 if (child_threads_active == threads_per_child ) {
@@ -3338,6 +3345,21 @@ static void perform_idle_server_maintenance(int child_bucket,
33383345 && retained -> total_daemons <= retained -> max_daemon_used
33393346 && retained -> max_daemon_used <= server_limit );
33403347
3348+ if (idle_termination_timeout >= 0 ) {
3349+ if (idle_thread_count == total_thread_count ) {
3350+ /* we are completely idle, decrease and check the timer */
3351+ if (-- idle_termination_remaining < 0 ) {
3352+ /* the termination timeout has expired, inform us we want to terminate immediately */
3353+ retained -> mpm -> shutdown_pending = 1 ;
3354+ retained -> mpm -> is_ungraceful = 1 ;
3355+ retained -> idle_timeout = 1 ;
3356+ }
3357+ } else {
3358+ /* not idle, reset the timer */
3359+ idle_termination_remaining = idle_termination_timeout ;
3360+ }
3361+ }
3362+
33413363 if (idle_thread_count > max_spare_threads / num_buckets ) {
33423364 /*
33433365 * Child processes that we ask to shut down won't die immediately
@@ -3783,8 +3805,15 @@ static int event_run(apr_pool_t * _pconf, apr_pool_t * plog, server_rec * s)
37833805 if (!child_fatal ) {
37843806 /* cleanup pid file on normal shutdown */
37853807 ap_remove_pid (pconf , ap_pid_fname );
3786- ap_log_error (APLOG_MARK , APLOG_NOTICE , 0 ,
3787- ap_server_conf , APLOGNO (00491 ) "caught SIGTERM, shutting down" );
3808+
3809+ /* log message depends on if we are terminating by signal or by idle timeout */
3810+ if (!retained -> idle_timeout ) {
3811+ ap_log_error (APLOG_MARK , APLOG_NOTICE , 0 , ap_server_conf , APLOGNO (00491 )
3812+ "caught SIGTERM, shutting down" );
3813+ } else {
3814+ ap_log_error (APLOG_MARK , APLOG_NOTICE , 0 , ap_server_conf , APLOGNO (00491 )
3815+ "idle timeout reached, shutting down" );
3816+ }
37883817 }
37893818
37903819 return DONE ;
@@ -4481,6 +4510,17 @@ static const char *set_worker_factor(cmd_parms * cmd, void *dummy,
44814510 return NULL ;
44824511}
44834512
4513+ static const char * set_idle_termination_timeout (cmd_parms * cmd , void * dummy , const char * arg )
4514+ {
4515+ const char * err = ap_check_cmd_context (cmd , GLOBAL_ONLY );
4516+ if (err != NULL ) {
4517+ return err ;
4518+ }
4519+
4520+ idle_termination_timeout = atoi (arg );
4521+ idle_termination_remaining = idle_termination_timeout ;
4522+ return NULL ;
4523+ }
44844524
44854525static const command_rec event_cmds [] = {
44864526 LISTEN_COMMANDS ,
@@ -4504,6 +4544,8 @@ static const command_rec event_cmds[] = {
45044544 AP_INIT_TAKE1 ("AsyncRequestWorkerFactor" , set_worker_factor , NULL , RSRC_CONF ,
45054545 "How many additional connects will be accepted per idle "
45064546 "worker thread" ),
4547+ AP_INIT_TAKE1 ("IdleTerminationTimeout" , set_idle_termination_timeout , NULL , RSRC_CONF ,
4548+ "Number of seconds to terminate in when the server is idle" ),
45074549 AP_GRACEFUL_SHUTDOWN_TIMEOUT_COMMAND ,
45084550 {NULL }
45094551};
0 commit comments