aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMaxim Dounin <mdounin@mdounin.ru>2017-03-07 18:51:16 +0300
committerMaxim Dounin <mdounin@mdounin.ru>2017-03-07 18:51:16 +0300
commit12b9974d510d38574c6cfb28ee3e87540230c56e (patch)
treecf66752182343de8606a9ac2d9625508d574356b
parent1a58418ae76a96c830a0536432e96a9ad051bc58 (diff)
downloadnginx-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.c9
-rw-r--r--src/core/ngx_cycle.c53
-rw-r--r--src/core/ngx_cycle.h2
-rw-r--r--src/os/unix/ngx_process_cycle.c1
-rw-r--r--src/os/win32/ngx_process_cycle.c1
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);
}