diff options
author | Maxim Dounin <mdounin@mdounin.ru> | 2017-03-07 18:51:16 +0300 |
---|---|---|
committer | Maxim Dounin <mdounin@mdounin.ru> | 2017-03-07 18:51:16 +0300 |
commit | 12b9974d510d38574c6cfb28ee3e87540230c56e (patch) | |
tree | cf66752182343de8606a9ac2d9625508d574356b | |
parent | 1a58418ae76a96c830a0536432e96a9ad051bc58 (diff) | |
download | nginx-12b9974d510d38574c6cfb28ee3e87540230c56e.tar.gz nginx-12b9974d510d38574c6cfb28ee3e87540230c56e.zip |
Introduced worker_shutdown_timeout.
The directive configures a timeout to be used when gracefully shutting down
worker processes. When the timer expires, nginx will try to close all
the connections currently open to facilitate shutdown.
-rw-r--r-- | src/core/nginx.c | 9 | ||||
-rw-r--r-- | src/core/ngx_cycle.c | 53 | ||||
-rw-r--r-- | src/core/ngx_cycle.h | 2 | ||||
-rw-r--r-- | src/os/unix/ngx_process_cycle.c | 1 | ||||
-rw-r--r-- | src/os/win32/ngx_process_cycle.c | 1 |
5 files changed, 66 insertions, 0 deletions
diff --git a/src/core/nginx.c b/src/core/nginx.c index c5f09a553..abaa50d61 100644 --- a/src/core/nginx.c +++ b/src/core/nginx.c @@ -124,6 +124,13 @@ static ngx_command_t ngx_core_commands[] = { offsetof(ngx_core_conf_t, rlimit_core), NULL }, + { ngx_string("worker_shutdown_timeout"), + NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_TAKE1, + ngx_conf_set_msec_slot, + 0, + offsetof(ngx_core_conf_t, shutdown_timeout), + NULL }, + { ngx_string("working_directory"), NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_TAKE1, ngx_conf_set_str_slot, @@ -1014,6 +1021,7 @@ ngx_core_module_create_conf(ngx_cycle_t *cycle) ccf->daemon = NGX_CONF_UNSET; ccf->master = NGX_CONF_UNSET; ccf->timer_resolution = NGX_CONF_UNSET_MSEC; + ccf->shutdown_timeout = NGX_CONF_UNSET_MSEC; ccf->worker_processes = NGX_CONF_UNSET; ccf->debug_points = NGX_CONF_UNSET; @@ -1042,6 +1050,7 @@ ngx_core_module_init_conf(ngx_cycle_t *cycle, void *conf) ngx_conf_init_value(ccf->daemon, 1); ngx_conf_init_value(ccf->master, 1); ngx_conf_init_msec_value(ccf->timer_resolution, 0); + ngx_conf_init_msec_value(ccf->shutdown_timeout, 0); ngx_conf_init_value(ccf->worker_processes, 1); ngx_conf_init_value(ccf->debug_points, 0); diff --git a/src/core/ngx_cycle.c b/src/core/ngx_cycle.c index 5e95628bf..3dfdf2e6f 100644 --- a/src/core/ngx_cycle.c +++ b/src/core/ngx_cycle.c @@ -15,6 +15,7 @@ static ngx_int_t ngx_init_zone_pool(ngx_cycle_t *cycle, ngx_shm_zone_t *shm_zone); static ngx_int_t ngx_test_lockfile(u_char *file, ngx_log_t *log); static void ngx_clean_old_cycles(ngx_event_t *ev); +static void ngx_shutdown_timer_handler(ngx_event_t *ev); volatile ngx_cycle_t *ngx_cycle; @@ -22,6 +23,7 @@ ngx_array_t ngx_old_cycles; static ngx_pool_t *ngx_temp_pool; static ngx_event_t ngx_cleaner_event; +static ngx_event_t ngx_shutdown_event; ngx_uint_t ngx_test_config; ngx_uint_t ngx_dump_config; @@ -1333,3 +1335,54 @@ ngx_clean_old_cycles(ngx_event_t *ev) ngx_old_cycles.nelts = 0; } } + + +void +ngx_set_shutdown_timer(ngx_cycle_t *cycle) +{ + ngx_core_conf_t *ccf; + + ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_core_module); + + if (ccf->shutdown_timeout) { + ngx_shutdown_event.handler = ngx_shutdown_timer_handler; + ngx_shutdown_event.data = cycle; + ngx_shutdown_event.log = cycle->log; + ngx_shutdown_event.cancelable = 1; + + ngx_add_timer(&ngx_shutdown_event, ccf->shutdown_timeout); + } +} + + +static void +ngx_shutdown_timer_handler(ngx_event_t *ev) +{ + ngx_uint_t i; + ngx_cycle_t *cycle; + ngx_connection_t *c; + + cycle = ev->data; + + c = cycle->connections; + + for (i = 0; i < cycle->connection_n; i++) { + + if (c[i].fd == (ngx_socket_t) -1 + || c[i].read == NULL + || c[i].read->accept + || c[i].read->channel + || c[i].read->resolver) + { + continue; + } + + ngx_log_debug1(NGX_LOG_DEBUG_CORE, ev->log, 0, + "*%uA shutdown timeout", c[i].number); + + c[i].close = 1; + c[i].error = 1; + + c[i].read->handler(c[i].read); + } +} diff --git a/src/core/ngx_cycle.h b/src/core/ngx_cycle.h index d804eb414..2b48ccbd6 100644 --- a/src/core/ngx_cycle.h +++ b/src/core/ngx_cycle.h @@ -88,6 +88,7 @@ typedef struct { ngx_flag_t master; ngx_msec_t timer_resolution; + ngx_msec_t shutdown_timeout; ngx_int_t worker_processes; ngx_int_t debug_points; @@ -129,6 +130,7 @@ ngx_pid_t ngx_exec_new_binary(ngx_cycle_t *cycle, char *const *argv); ngx_cpuset_t *ngx_get_cpu_affinity(ngx_uint_t n); ngx_shm_zone_t *ngx_shared_memory_add(ngx_conf_t *cf, ngx_str_t *name, size_t size, void *tag); +void ngx_set_shutdown_timer(ngx_cycle_t *cycle); extern volatile ngx_cycle_t *ngx_cycle; diff --git a/src/os/unix/ngx_process_cycle.c b/src/os/unix/ngx_process_cycle.c index d0c61143e..785888fc4 100644 --- a/src/os/unix/ngx_process_cycle.c +++ b/src/os/unix/ngx_process_cycle.c @@ -763,6 +763,7 @@ ngx_worker_process_cycle(ngx_cycle_t *cycle, void *data) if (!ngx_exiting) { ngx_exiting = 1; + ngx_set_shutdown_timer(cycle); ngx_close_listening_sockets(cycle); ngx_close_idle_connections(cycle); } diff --git a/src/os/win32/ngx_process_cycle.c b/src/os/win32/ngx_process_cycle.c index 5b2df3858..293b967ec 100644 --- a/src/os/win32/ngx_process_cycle.c +++ b/src/os/win32/ngx_process_cycle.c @@ -800,6 +800,7 @@ ngx_worker_thread(void *data) if (!ngx_exiting) { ngx_exiting = 1; + ngx_set_shutdown_timer(cycle); ngx_close_listening_sockets(cycle); ngx_close_idle_connections(cycle); } |