logo

oasis

Own branch of Oasis Linux (upstream: <https://git.sr.ht/~mcf/oasis/>) git clone https://anongit.hacktivis.me/git/oasis.git
commit: 4b02639f2d50d8c137750f603abf1390c3477ca2
parent 162ec3384ea56e878a1a44694c071d17cc71d8fc
Author: Michael Forney <mforney@mforney.org>
Date:   Sun,  5 Jul 2020 15:22:58 -0700

nginx: Fix for TCP reset after http2_max_requests

Diffstat:

M.gitmodules1+
Apkg/nginx/patch/0001-HTTP-2-lingering-close-after-GOAWAY.patch213+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mpkg/nginx/ver2+-
3 files changed, 215 insertions(+), 1 deletion(-)

diff --git a/.gitmodules b/.gitmodules @@ -231,6 +231,7 @@ [submodule "pkg/nginx/src"] path = pkg/nginx/src url = https://github.com/nginx/nginx + ignore = all [submodule "pkg/oksh/src"] path = pkg/oksh/src url = https://github.com/ibara/oksh.git diff --git a/pkg/nginx/patch/0001-HTTP-2-lingering-close-after-GOAWAY.patch b/pkg/nginx/patch/0001-HTTP-2-lingering-close-after-GOAWAY.patch @@ -0,0 +1,213 @@ +From 33a5a57ec7d114e52865e11527660249b996f56e Mon Sep 17 00:00:00 2001 +From: Ruslan Ermilov <ru@nginx.com> +Date: Fri, 3 Jul 2020 16:16:47 +0300 +Subject: [PATCH] HTTP/2: lingering close after GOAWAY. + +After sending the GOAWAY frame, a connection is now closed using +the lingering close mechanism. + +This allows for the reliable delivery of the GOAWAY frames, while +also fixing connection resets observed when http2_max_requests is +reached (ticket #1250), or with graceful shutdown (ticket #1544), +when some additional data from the client is received on a fully +closed connection. + +For HTTP/2, the settings lingering_close, lingering_timeout, and +lingering_time are taken from the "server" level. +--- + src/http/v2/ngx_http_v2.c | 128 ++++++++++++++++++++++++++++++++++++-- + src/http/v2/ngx_http_v2.h | 2 + + 2 files changed, 124 insertions(+), 6 deletions(-) + +diff --git a/src/http/v2/ngx_http_v2.c b/src/http/v2/ngx_http_v2.c +index 8b0fc53b..48733fe3 100644 +--- a/src/http/v2/ngx_http_v2.c ++++ b/src/http/v2/ngx_http_v2.c +@@ -60,6 +60,8 @@ typedef struct { + static void ngx_http_v2_read_handler(ngx_event_t *rev); + static void ngx_http_v2_write_handler(ngx_event_t *wev); + static void ngx_http_v2_handle_connection(ngx_http_v2_connection_t *h2c); ++static void ngx_http_v2_lingering_close(ngx_http_v2_connection_t *h2c); ++static void ngx_http_v2_lingering_close_handler(ngx_event_t *rev); + + static u_char *ngx_http_v2_state_proxy_protocol(ngx_http_v2_connection_t *h2c, + u_char *pos, u_char *end); +@@ -661,7 +663,7 @@ ngx_http_v2_handle_connection(ngx_http_v2_connection_t *h2c) + } + + if (h2c->goaway) { +- ngx_http_close_connection(c); ++ ngx_http_v2_lingering_close(h2c); + return; + } + +@@ -699,6 +701,113 @@ ngx_http_v2_handle_connection(ngx_http_v2_connection_t *h2c) + } + + ++static void ++ngx_http_v2_lingering_close(ngx_http_v2_connection_t *h2c) ++{ ++ ngx_event_t *rev, *wev; ++ ngx_connection_t *c; ++ ngx_http_core_loc_conf_t *clcf; ++ ++ c = h2c->connection; ++ ++ clcf = ngx_http_get_module_loc_conf(h2c->http_connection->conf_ctx, ++ ngx_http_core_module); ++ ++ if (clcf->lingering_close == NGX_HTTP_LINGERING_OFF) { ++ ngx_http_close_connection(c); ++ return; ++ } ++ ++ rev = c->read; ++ rev->handler = ngx_http_v2_lingering_close_handler; ++ ++ h2c->lingering_time = ngx_time() + (time_t) (clcf->lingering_time / 1000); ++ ngx_add_timer(rev, clcf->lingering_timeout); ++ ++ if (ngx_handle_read_event(rev, 0) != NGX_OK) { ++ ngx_http_close_connection(c); ++ return; ++ } ++ ++ wev = c->write; ++ wev->handler = ngx_http_empty_handler; ++ ++ if (wev->active && (ngx_event_flags & NGX_USE_LEVEL_EVENT)) { ++ if (ngx_del_event(wev, NGX_WRITE_EVENT, 0) != NGX_OK) { ++ ngx_http_close_connection(c); ++ return; ++ } ++ } ++ ++ if (ngx_shutdown_socket(c->fd, NGX_WRITE_SHUTDOWN) == -1) { ++ ngx_connection_error(c, ngx_socket_errno, ++ ngx_shutdown_socket_n " failed"); ++ ngx_http_close_connection(c); ++ return; ++ } ++ ++ if (rev->ready) { ++ ngx_http_v2_lingering_close_handler(rev); ++ } ++} ++ ++ ++static void ++ngx_http_v2_lingering_close_handler(ngx_event_t *rev) ++{ ++ ssize_t n; ++ ngx_msec_t timer; ++ ngx_connection_t *c; ++ ngx_http_core_loc_conf_t *clcf; ++ ngx_http_v2_connection_t *h2c; ++ u_char buffer[NGX_HTTP_LINGERING_BUFFER_SIZE]; ++ ++ c = rev->data; ++ h2c = c->data; ++ ++ ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, ++ "http2 lingering close handler"); ++ ++ if (rev->timedout) { ++ ngx_http_close_connection(c); ++ return; ++ } ++ ++ timer = (ngx_msec_t) h2c->lingering_time - (ngx_msec_t) ngx_time(); ++ if ((ngx_msec_int_t) timer <= 0) { ++ ngx_http_close_connection(c); ++ return; ++ } ++ ++ do { ++ n = c->recv(c, buffer, NGX_HTTP_LINGERING_BUFFER_SIZE); ++ ++ ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, "lingering read: %z", n); ++ ++ if (n == NGX_ERROR || n == 0) { ++ ngx_http_close_connection(c); ++ return; ++ } ++ ++ } while (rev->ready); ++ ++ if (ngx_handle_read_event(rev, 0) != NGX_OK) { ++ ngx_http_close_connection(c); ++ return; ++ } ++ ++ clcf = ngx_http_get_module_loc_conf(h2c->http_connection->conf_ctx, ++ ngx_http_core_module); ++ timer *= 1000; ++ ++ if (timer > clcf->lingering_timeout) { ++ timer = clcf->lingering_timeout; ++ } ++ ++ ngx_add_timer(rev, timer); ++} ++ ++ + static u_char * + ngx_http_v2_state_proxy_protocol(ngx_http_v2_connection_t *h2c, u_char *pos, + u_char *end) +@@ -4543,16 +4652,15 @@ ngx_http_v2_finalize_connection(ngx_http_v2_connection_t *h2c, + h2c->blocked = 1; + + if (!c->error && !h2c->goaway) { ++ h2c->goaway = 1; ++ + if (ngx_http_v2_send_goaway(h2c, status) != NGX_ERROR) { + (void) ngx_http_v2_send_output_queue(h2c); + } + } + +- c->error = 1; +- + if (!h2c->processing && !h2c->pushing) { +- ngx_http_close_connection(c); +- return; ++ goto done; + } + + c->read->handler = ngx_http_empty_handler; +@@ -4600,10 +4708,18 @@ ngx_http_v2_finalize_connection(ngx_http_v2_connection_t *h2c, + h2c->blocked = 0; + + if (h2c->processing || h2c->pushing) { ++ c->error = 1; ++ return; ++ } ++ ++done: ++ ++ if (c->error) { ++ ngx_http_close_connection(c); + return; + } + +- ngx_http_close_connection(c); ++ ngx_http_v2_lingering_close(h2c); + } + + +diff --git a/src/http/v2/ngx_http_v2.h b/src/http/v2/ngx_http_v2.h +index 59ddf54e..34922971 100644 +--- a/src/http/v2/ngx_http_v2.h ++++ b/src/http/v2/ngx_http_v2.h +@@ -157,6 +157,8 @@ struct ngx_http_v2_connection_s { + ngx_uint_t last_sid; + ngx_uint_t last_push; + ++ time_t lingering_time; ++ + unsigned closed_nodes:8; + unsigned settings_ack:1; + unsigned table_update:1; +-- +2.27.0 + diff --git a/pkg/nginx/ver b/pkg/nginx/ver @@ -1 +1 @@ -1.18.0 r0 +1.18.0 r1