changeset 7538:08ed570ad93c

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.
author Maxim Dounin <mdounin@mdounin.ru>
date Thu, 18 Jul 2019 18:27:52 +0300
parents 01e26357916a
children d75153522557
files src/http/ngx_http_upstream.c
diffstat 1 files changed, 26 insertions(+), 3 deletions(-) [+]
line wrap: on
line diff
--- a/src/http/ngx_http_upstream.c
+++ b/src/http/ngx_http_upstream.c
@@ -3334,6 +3334,7 @@ ngx_http_upstream_process_upgraded(ngx_h
     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_h
         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_h
         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_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_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;
     }