]> git.kaiwu.me - nginx.git/commitdiff
Introduced worker_shutdown_timeout.
authorMaxim Dounin <mdounin@mdounin.ru>
Tue, 7 Mar 2017 15:51:16 +0000 (18:51 +0300)
committerMaxim Dounin <mdounin@mdounin.ru>
Tue, 7 Mar 2017 15:51:16 +0000 (18:51 +0300)
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.

src/core/nginx.c
src/core/ngx_cycle.c
src/core/ngx_cycle.h
src/os/unix/ngx_process_cycle.c
src/os/win32/ngx_process_cycle.c

index c5f09a553c1fdf9fe02f91b8136028a86244a3d0..abaa50d618496073d97c8c13b601da9447317f4b 100644 (file)
@@ -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);
index 5e95628bfd97575a6f408fa4de707ed57784ab5b..3dfdf2e6fac8da05e68fd15e8c042a211314a448 100644 (file)
@@ -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);
+    }
+}
index d804eb414998ac735d4a52ed897b76ae900bee6a..2b48ccbd6ddd1b33f6038ca7c1418082d1714d8b 100644 (file)
@@ -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;
index d0c61143e883dcfb812d707d6695ce5901b9ac78..785888fc4935a3cdfd975dc915dcf2d8a7a2288a 100644 (file)
@@ -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);
             }
index 5b2df3858bc2caedff403d8f91bd42c1eb377d5f..293b967ec457b4ff3382b3124a818359092c56c2 100644 (file)
@@ -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);
             }