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.
This commit is contained in:
Maxim Dounin 2017-03-07 18:51:15 +03:00
parent 0212c7fac1
commit 1a58418ae7
4 changed files with 18 additions and 37 deletions

View File

@ -96,43 +96,31 @@ ngx_event_expire_timers(void)
} }
void ngx_int_t
ngx_event_cancel_timers(void) ngx_event_no_timers_left(void)
{ {
ngx_event_t *ev; ngx_event_t *ev;
ngx_rbtree_node_t *node, *root, *sentinel; ngx_rbtree_node_t *node, *root, *sentinel;
sentinel = ngx_event_timer_rbtree.sentinel; sentinel = ngx_event_timer_rbtree.sentinel;
for ( ;; ) {
root = ngx_event_timer_rbtree.root; root = ngx_event_timer_rbtree.root;
if (root == sentinel) { if (root == sentinel) {
return; 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)); ev = (ngx_event_t *) ((char *) node - offsetof(ngx_event_t, timer));
if (!ev->cancelable) { if (!ev->cancelable) {
return; return NGX_AGAIN;
}
} }
ngx_log_debug2(NGX_LOG_DEBUG_EVENT, ev->log, 0, /* only cancelable timers left */
"event timer cancel: %d: %M",
ngx_event_ident(ev->data), ev->timer.key);
ngx_rbtree_delete(&ngx_event_timer_rbtree, &ev->timer); return NGX_OK;
#if (NGX_DEBUG)
ev->timer.left = NULL;
ev->timer.right = NULL;
ev->timer.parent = NULL;
#endif
ev->timer_set = 0;
ev->handler(ev);
}
} }

View File

@ -22,7 +22,7 @@
ngx_int_t ngx_event_timer_init(ngx_log_t *log); ngx_int_t ngx_event_timer_init(ngx_log_t *log);
ngx_msec_t ngx_event_find_timer(void); ngx_msec_t ngx_event_find_timer(void);
void ngx_event_expire_timers(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; extern ngx_rbtree_t ngx_event_timer_rbtree;

View File

@ -738,10 +738,7 @@ ngx_worker_process_cycle(ngx_cycle_t *cycle, void *data)
for ( ;; ) { for ( ;; ) {
if (ngx_exiting) { if (ngx_exiting) {
ngx_event_cancel_timers(); if (ngx_event_no_timers_left() == NGX_OK) {
if (ngx_event_timer_rbtree.root == ngx_event_timer_rbtree.sentinel)
{
ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "exiting"); ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "exiting");
ngx_worker_process_exit(cycle); ngx_worker_process_exit(cycle);

View File

@ -782,11 +782,7 @@ ngx_worker_thread(void *data)
while (!ngx_quit) { while (!ngx_quit) {
if (ngx_exiting) { if (ngx_exiting) {
ngx_event_cancel_timers(); if (ngx_event_no_timers_left() == NGX_OK) {
if (ngx_event_timer_rbtree.root
== ngx_event_timer_rbtree.sentinel)
{
break; break;
} }
} }