# HG changeset patch # User Maxim Dounin # Date 1521317062 -10800 # Node ID 22f7bdbd96d33e8fe84468ec069f0131a139e717 # Parent 098bbd076a2de78a1059e9f5de92b77415f0f4a9 Upstream: u->request_body_blocked flag. The flag indicates whether last ngx_output_chain() returned NGX_AGAIN or not. If the flag is set, we arm the u->conf->send_timeout timer. The flag complements c->write->ready test, and allows to stop sending the request body in an output filter due to protocol-specific flow control. diff -r 098bbd076a2d -r 22f7bdbd96d3 src/http/ngx_http_upstream.c --- a/src/http/ngx_http_upstream.c Sat Mar 17 23:04:21 2018 +0300 +++ b/src/http/ngx_http_upstream.c Sat Mar 17 23:04:22 2018 +0300 @@ -1616,6 +1616,7 @@ u->request_sent = 0; u->request_body_sent = 0; + u->request_body_blocked = 0; if (rc == NGX_AGAIN) { ngx_add_timer(c->write, u->conf->connect_timeout); @@ -1994,7 +1995,7 @@ } if (rc == NGX_AGAIN) { - if (!c->write->ready) { + if (!c->write->ready || u->request_body_blocked) { ngx_add_timer(c->write, u->conf->send_timeout); } else if (c->write->timer_set) { @@ -2071,7 +2072,16 @@ out = NULL; } - return ngx_output_chain(&u->output, out); + rc = ngx_output_chain(&u->output, out); + + if (rc == NGX_AGAIN) { + u->request_body_blocked = 1; + + } else { + u->request_body_blocked = 0; + } + + return rc; } if (!u->request_sent) { @@ -2112,6 +2122,13 @@ ngx_free_chain(r->pool, ln); } + if (rc == NGX_AGAIN) { + u->request_body_blocked = 1; + + } else { + u->request_body_blocked = 0; + } + if (rc == NGX_OK && !r->reading_body) { break; } diff -r 098bbd076a2d -r 22f7bdbd96d3 src/http/ngx_http_upstream.h --- a/src/http/ngx_http_upstream.h Sat Mar 17 23:04:21 2018 +0300 +++ b/src/http/ngx_http_upstream.h Sat Mar 17 23:04:22 2018 +0300 @@ -391,6 +391,7 @@ unsigned request_sent:1; unsigned request_body_sent:1; + unsigned request_body_blocked:1; unsigned header_sent:1; };