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.
Maxim Dounin
5 years ago
121 | 121 | ngx_conf_set_off_slot, |
122 | 122 | 0, |
123 | 123 | offsetof(ngx_core_conf_t, rlimit_core), |
124 | NULL }, | |
125 | ||
126 | { ngx_string("worker_shutdown_timeout"), | |
127 | NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_TAKE1, | |
128 | ngx_conf_set_msec_slot, | |
129 | 0, | |
130 | offsetof(ngx_core_conf_t, shutdown_timeout), | |
124 | 131 | NULL }, |
125 | 132 | |
126 | 133 | { ngx_string("working_directory"), |
1013 | 1020 | ccf->daemon = NGX_CONF_UNSET; |
1014 | 1021 | ccf->master = NGX_CONF_UNSET; |
1015 | 1022 | ccf->timer_resolution = NGX_CONF_UNSET_MSEC; |
1023 | ccf->shutdown_timeout = NGX_CONF_UNSET_MSEC; | |
1016 | 1024 | |
1017 | 1025 | ccf->worker_processes = NGX_CONF_UNSET; |
1018 | 1026 | ccf->debug_points = NGX_CONF_UNSET; |
1041 | 1049 | ngx_conf_init_value(ccf->daemon, 1); |
1042 | 1050 | ngx_conf_init_value(ccf->master, 1); |
1043 | 1051 | ngx_conf_init_msec_value(ccf->timer_resolution, 0); |
1052 | ngx_conf_init_msec_value(ccf->shutdown_timeout, 0); | |
1044 | 1053 | |
1045 | 1054 | ngx_conf_init_value(ccf->worker_processes, 1); |
1046 | 1055 | ngx_conf_init_value(ccf->debug_points, 0); |
14 | 14 | ngx_shm_zone_t *shm_zone); |
15 | 15 | static ngx_int_t ngx_test_lockfile(u_char *file, ngx_log_t *log); |
16 | 16 | static void ngx_clean_old_cycles(ngx_event_t *ev); |
17 | static void ngx_shutdown_timer_handler(ngx_event_t *ev); | |
17 | 18 | |
18 | 19 | |
19 | 20 | volatile ngx_cycle_t *ngx_cycle; |
21 | 22 | |
22 | 23 | static ngx_pool_t *ngx_temp_pool; |
23 | 24 | static ngx_event_t ngx_cleaner_event; |
25 | static ngx_event_t ngx_shutdown_event; | |
24 | 26 | |
25 | 27 | ngx_uint_t ngx_test_config; |
26 | 28 | ngx_uint_t ngx_dump_config; |
1332 | 1334 | ngx_old_cycles.nelts = 0; |
1333 | 1335 | } |
1334 | 1336 | } |
1337 | ||
1338 | ||
1339 | void | |
1340 | ngx_set_shutdown_timer(ngx_cycle_t *cycle) | |
1341 | { | |
1342 | ngx_core_conf_t *ccf; | |
1343 | ||
1344 | ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_core_module); | |
1345 | ||
1346 | if (ccf->shutdown_timeout) { | |
1347 | ngx_shutdown_event.handler = ngx_shutdown_timer_handler; | |
1348 | ngx_shutdown_event.data = cycle; | |
1349 | ngx_shutdown_event.log = cycle->log; | |
1350 | ngx_shutdown_event.cancelable = 1; | |
1351 | ||
1352 | ngx_add_timer(&ngx_shutdown_event, ccf->shutdown_timeout); | |
1353 | } | |
1354 | } | |
1355 | ||
1356 | ||
1357 | static void | |
1358 | ngx_shutdown_timer_handler(ngx_event_t *ev) | |
1359 | { | |
1360 | ngx_uint_t i; | |
1361 | ngx_cycle_t *cycle; | |
1362 | ngx_connection_t *c; | |
1363 | ||
1364 | cycle = ev->data; | |
1365 | ||
1366 | c = cycle->connections; | |
1367 | ||
1368 | for (i = 0; i < cycle->connection_n; i++) { | |
1369 | ||
1370 | if (c[i].fd == (ngx_socket_t) -1 | |
1371 | || c[i].read == NULL | |
1372 | || c[i].read->accept | |
1373 | || c[i].read->channel | |
1374 | || c[i].read->resolver) | |
1375 | { | |
1376 | continue; | |
1377 | } | |
1378 | ||
1379 | ngx_log_debug1(NGX_LOG_DEBUG_CORE, ev->log, 0, | |
1380 | "*%uA shutdown timeout", c[i].number); | |
1381 | ||
1382 | c[i].close = 1; | |
1383 | c[i].error = 1; | |
1384 | ||
1385 | c[i].read->handler(c[i].read); | |
1386 | } | |
1387 | } |
87 | 87 | ngx_flag_t master; |
88 | 88 | |
89 | 89 | ngx_msec_t timer_resolution; |
90 | ngx_msec_t shutdown_timeout; | |
90 | 91 | |
91 | 92 | ngx_int_t worker_processes; |
92 | 93 | ngx_int_t debug_points; |
128 | 129 | ngx_cpuset_t *ngx_get_cpu_affinity(ngx_uint_t n); |
129 | 130 | ngx_shm_zone_t *ngx_shared_memory_add(ngx_conf_t *cf, ngx_str_t *name, |
130 | 131 | size_t size, void *tag); |
132 | void ngx_set_shutdown_timer(ngx_cycle_t *cycle); | |
131 | 133 | |
132 | 134 | |
133 | 135 | extern volatile ngx_cycle_t *ngx_cycle; |