Mercurial > hg > nginx
view src/event/ngx_event_timer.c @ 7958:9b72da2b5b57 stable-1.20
SSL: set events ready flags after handshake.
The c->read->ready and c->write->ready flags might be reset during
the handshake, and not set again if the handshake was finished on
the other event. At the same time, some data might be read from
the socket during the handshake, so missing c->read->ready flag might
result in a connection hang, for example, when waiting for an SMTP
greeting (which was already received during the handshake).
Found by Sergey Kandaurov.
author | Maxim Dounin <mdounin@mdounin.ru> |
---|---|
date | Tue, 03 Aug 2021 20:50:30 +0300 |
parents | 03928f7f209b |
children | 0c5e84096d99 |
line wrap: on
line source
/* * Copyright (C) Igor Sysoev * Copyright (C) Nginx, Inc. */ #include <ngx_config.h> #include <ngx_core.h> #include <ngx_event.h> ngx_rbtree_t ngx_event_timer_rbtree; static ngx_rbtree_node_t ngx_event_timer_sentinel; /* * the event timer rbtree may contain the duplicate keys, however, * it should not be a problem, because we use the rbtree to find * a minimum timer value only */ ngx_int_t ngx_event_timer_init(ngx_log_t *log) { ngx_rbtree_init(&ngx_event_timer_rbtree, &ngx_event_timer_sentinel, ngx_rbtree_insert_timer_value); return NGX_OK; } ngx_msec_t ngx_event_find_timer(void) { ngx_msec_int_t timer; ngx_rbtree_node_t *node, *root, *sentinel; if (ngx_event_timer_rbtree.root == &ngx_event_timer_sentinel) { return NGX_TIMER_INFINITE; } root = ngx_event_timer_rbtree.root; sentinel = ngx_event_timer_rbtree.sentinel; node = ngx_rbtree_min(root, sentinel); timer = (ngx_msec_int_t) (node->key - ngx_current_msec); return (ngx_msec_t) (timer > 0 ? timer : 0); } void ngx_event_expire_timers(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; if (root == sentinel) { return; } node = ngx_rbtree_min(root, sentinel); /* node->key > ngx_current_msec */ if ((ngx_msec_int_t) (node->key - ngx_current_msec) > 0) { return; } ev = (ngx_event_t *) ((char *) node - offsetof(ngx_event_t, timer)); ngx_log_debug2(NGX_LOG_DEBUG_EVENT, ev->log, 0, "event timer del: %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 ev->timer_set = 0; ev->timedout = 1; ev->handler(ev); } } 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; root = ngx_event_timer_rbtree.root; if (root == sentinel) { return NGX_OK; } 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 NGX_AGAIN; } } /* only cancelable timers left */ return NGX_OK; }