From 179c79ce8afd459acffa50e6dabc60b0b7d9a014 Mon Sep 17 00:00:00 2001 From: Maxim Dounin Date: Sun, 28 Mar 2021 17:45:39 +0300 Subject: [PATCH] Fixed handling of already closed connections. In limit_req, auth_delay, and upstream code to check for broken connections, tests for possible connection close by the client did not work if the connection was already closed when relevant event handler was set. This happened because there were no additional events in case of edge-triggered event methods, and read events were disabled in case of level-triggered ones. Fix is to explicitly post a read event if the c->read->ready flag is set. --- src/http/modules/ngx_http_limit_req_module.c | 9 +++++++-- src/http/ngx_http_core_module.c | 9 +++++++-- src/http/ngx_http_upstream.c | 11 ++++++++--- 3 files changed, 22 insertions(+), 7 deletions(-) diff --git a/src/http/modules/ngx_http_limit_req_module.c b/src/http/modules/ngx_http_limit_req_module.c index dad5edb93..2b062a305 100644 --- a/src/http/modules/ngx_http_limit_req_module.c +++ b/src/http/modules/ngx_http_limit_req_module.c @@ -310,8 +310,13 @@ ngx_http_limit_req_handler(ngx_http_request_t *r) r->main->limit_req_status = NGX_HTTP_LIMIT_REQ_DELAYED; - if (ngx_handle_read_event(r->connection->read, 0) != NGX_OK) { - return NGX_HTTP_INTERNAL_SERVER_ERROR; + if (r->connection->read->ready) { + ngx_post_event(r->connection->read, &ngx_posted_events); + + } else { + if (ngx_handle_read_event(r->connection->read, 0) != NGX_OK) { + return NGX_HTTP_INTERNAL_SERVER_ERROR; + } } r->read_event_handler = ngx_http_test_reading; diff --git a/src/http/ngx_http_core_module.c b/src/http/ngx_http_core_module.c index 67476e7d7..9b94b328e 100644 --- a/src/http/ngx_http_core_module.c +++ b/src/http/ngx_http_core_module.c @@ -1190,8 +1190,13 @@ ngx_http_core_auth_delay(ngx_http_request_t *r) ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, "delaying unauthorized request"); - if (ngx_handle_read_event(r->connection->read, 0) != NGX_OK) { - return NGX_HTTP_INTERNAL_SERVER_ERROR; + if (r->connection->read->ready) { + ngx_post_event(r->connection->read, &ngx_posted_events); + + } else { + if (ngx_handle_read_event(r->connection->read, 0) != NGX_OK) { + return NGX_HTTP_INTERNAL_SERVER_ERROR; + } } r->read_event_handler = ngx_http_test_reading; diff --git a/src/http/ngx_http_upstream.c b/src/http/ngx_http_upstream.c index bd1627c09..1016afa5b 100644 --- a/src/http/ngx_http_upstream.c +++ b/src/http/ngx_http_upstream.c @@ -608,9 +608,14 @@ ngx_http_upstream_init_request(ngx_http_request_t *r) if (!u->store && !r->post_action && !u->conf->ignore_client_abort) { - if (ngx_handle_read_event(r->connection->read, 0) != NGX_OK) { - ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); - return; + if (r->connection->read->ready) { + ngx_post_event(r->connection->read, &ngx_posted_events); + + } else { + if (ngx_handle_read_event(r->connection->read, 0) != NGX_OK) { + ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); + return; + } } r->read_event_handler = ngx_http_upstream_rd_check_broken_connection;