From 20c8c4fe35d290abe298cea9a4f1756fcfec19f4 Mon Sep 17 00:00:00 2001 From: Maxim Dounin Date: Thu, 18 Jul 2019 18:27:52 +0300 Subject: [PATCH] Upstream: fixed EOF handling in unbuffered and upgraded modes. With level-triggered event methods it is important to specify the NGX_CLOSE_EVENT flag to ngx_handle_read_event(), otherwise the event won't be removed, resulting in CPU hog. Reported by Patrick Wollgast. --- src/http/ngx_http_upstream.c | 29 ++++++++++++++++++++++++++--- 1 file changed, 26 insertions(+), 3 deletions(-) diff --git a/src/http/ngx_http_upstream.c b/src/http/ngx_http_upstream.c index ffb09a91f..89e1319f9 100644 --- a/src/http/ngx_http_upstream.c +++ b/src/http/ngx_http_upstream.c @@ -3334,6 +3334,7 @@ ngx_http_upstream_process_upgraded(ngx_http_request_t *r, size_t size; ssize_t n; ngx_buf_t *b; + ngx_uint_t flags; ngx_connection_t *c, *downstream, *upstream, *dst, *src; ngx_http_upstream_t *u; ngx_http_core_loc_conf_t *clcf; @@ -3472,7 +3473,14 @@ ngx_http_upstream_process_upgraded(ngx_http_request_t *r, ngx_del_timer(upstream->write); } - if (ngx_handle_read_event(upstream->read, 0) != NGX_OK) { + if (upstream->read->eof || upstream->read->error) { + flags = NGX_CLOSE_EVENT; + + } else { + flags = 0; + } + + if (ngx_handle_read_event(upstream->read, flags) != NGX_OK) { ngx_http_upstream_finalize_request(r, u, NGX_ERROR); return; } @@ -3491,7 +3499,14 @@ ngx_http_upstream_process_upgraded(ngx_http_request_t *r, return; } - if (ngx_handle_read_event(downstream->read, 0) != NGX_OK) { + if (downstream->read->eof || downstream->read->error) { + flags = NGX_CLOSE_EVENT; + + } else { + flags = 0; + } + + if (ngx_handle_read_event(downstream->read, flags) != NGX_OK) { ngx_http_upstream_finalize_request(r, u, NGX_ERROR); return; } @@ -3563,6 +3578,7 @@ ngx_http_upstream_process_non_buffered_request(ngx_http_request_t *r, ssize_t n; ngx_buf_t *b; ngx_int_t rc; + ngx_uint_t flags; ngx_connection_t *downstream, *upstream; ngx_http_upstream_t *u; ngx_http_core_loc_conf_t *clcf; @@ -3666,7 +3682,14 @@ ngx_http_upstream_process_non_buffered_request(ngx_http_request_t *r, ngx_del_timer(downstream->write); } - if (ngx_handle_read_event(upstream->read, 0) != NGX_OK) { + if (upstream->read->eof || upstream->read->error) { + flags = NGX_CLOSE_EVENT; + + } else { + flags = 0; + } + + if (ngx_handle_read_event(upstream->read, flags) != NGX_OK) { ngx_http_upstream_finalize_request(r, u, NGX_ERROR); return; }