# HG changeset patch # User Maxim Dounin # Date 1488901875 -10800 # Node ID 3069dd358ba24d675e786c49270c29fb89b34be9 # Parent e0cc454aafe4ed71779285ed7fc8b7feb9b8f384 Cancelable timers are now preserved if there are other timers. There is no need to cancel timers early if there are other timers blocking shutdown anyway. Preserving such timers allows nginx to continue some periodic work till the shutdown is actually possible. With the new approach, timers with ev->cancelable are simply ignored when checking if there are any timers left during shutdown. diff --git a/src/event/ngx_event_timer.c b/src/event/ngx_event_timer.c --- a/src/event/ngx_event_timer.c +++ b/src/event/ngx_event_timer.c @@ -96,43 +96,31 @@ ngx_event_expire_timers(void) } -void -ngx_event_cancel_timers(void) +ngx_int_t +ngx_event_no_timers_left(void) { ngx_event_t *ev; ngx_rbtree_node_t *node, *root, *sentinel; sentinel = ngx_event_timer_rbtree.sentinel; - - for ( ;; ) { - root = ngx_event_timer_rbtree.root; + root = ngx_event_timer_rbtree.root; - if (root == sentinel) { - return; - } + if (root == sentinel) { + return NGX_OK; + } - node = ngx_rbtree_min(root, sentinel); - + for (node = ngx_rbtree_min(root, sentinel); + node; + node = ngx_rbtree_next(&ngx_event_timer_rbtree, node)) + { ev = (ngx_event_t *) ((char *) node - offsetof(ngx_event_t, timer)); if (!ev->cancelable) { - return; + return NGX_AGAIN; } - - ngx_log_debug2(NGX_LOG_DEBUG_EVENT, ev->log, 0, - "event timer cancel: %d: %M", - ngx_event_ident(ev->data), ev->timer.key); - - ngx_rbtree_delete(&ngx_event_timer_rbtree, &ev->timer); + } -#if (NGX_DEBUG) - ev->timer.left = NULL; - ev->timer.right = NULL; - ev->timer.parent = NULL; -#endif + /* only cancelable timers left */ - ev->timer_set = 0; - - ev->handler(ev); - } + return NGX_OK; } diff --git a/src/event/ngx_event_timer.h b/src/event/ngx_event_timer.h --- a/src/event/ngx_event_timer.h +++ b/src/event/ngx_event_timer.h @@ -22,7 +22,7 @@ ngx_int_t ngx_event_timer_init(ngx_log_t *log); ngx_msec_t ngx_event_find_timer(void); void ngx_event_expire_timers(void); -void ngx_event_cancel_timers(void); +ngx_int_t ngx_event_no_timers_left(void); extern ngx_rbtree_t ngx_event_timer_rbtree; diff --git a/src/os/unix/ngx_process_cycle.c b/src/os/unix/ngx_process_cycle.c --- a/src/os/unix/ngx_process_cycle.c +++ b/src/os/unix/ngx_process_cycle.c @@ -738,10 +738,7 @@ ngx_worker_process_cycle(ngx_cycle_t *cy for ( ;; ) { if (ngx_exiting) { - ngx_event_cancel_timers(); - - if (ngx_event_timer_rbtree.root == ngx_event_timer_rbtree.sentinel) - { + if (ngx_event_no_timers_left() == NGX_OK) { ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "exiting"); ngx_worker_process_exit(cycle); diff --git a/src/os/win32/ngx_process_cycle.c b/src/os/win32/ngx_process_cycle.c --- a/src/os/win32/ngx_process_cycle.c +++ b/src/os/win32/ngx_process_cycle.c @@ -782,11 +782,7 @@ ngx_worker_thread(void *data) while (!ngx_quit) { if (ngx_exiting) { - ngx_event_cancel_timers(); - - if (ngx_event_timer_rbtree.root - == ngx_event_timer_rbtree.sentinel) - { + if (ngx_event_no_timers_left() == NGX_OK) { break; } }