[PATCH] ngx_gzip might hang the request for slow downstreams
Maxim Dounin
mdounin at mdounin.ru
Sat Oct 26 01:48:15 UTC 2013
Hello!
On Fri, Oct 25, 2013 at 05:16:24PM -0700, Yichun Zhang (agentzh) wrote:
> Hello!
>
> I've noticed a request hang due to an issue in
> ngx_http_gzip_filter_module's output body filter. Basically when the
> downstream connection is slow to write to, a write event can trigger a
> call of ngx_http_output_filter(r, NULL) but ngx_gzip's body filter
> does not pass the NULL chain link to its downstream filters when its
> ctx->out == NULL, leading to the downstream connection not flushed at
> all and a hang.
>
> This issue exists in both nginx 1.4.3 and 1.5.6.
>
> The following patch fixes the test case on my side. Comments welcome!
>
> Thanks!
> -agentzh
>
> --- nginx-1.4.3/src/http/modules/ngx_http_gzip_filter_module.c
> 2013-10-08 05:07:14.000000000 -0700
> +++ nginx-1.4.3-patched/src/http/modules/ngx_http_gzip_filter_module.c
> 2013-10-25 17:00:00.712697908 -0700
> @@ -433,7 +433,15 @@ ngx_http_gzip_body_filter(ngx_http_reque
> if (ctx->out == NULL) {
> ngx_http_gzip_filter_free_copy_buf(r, ctx);
>
> - return ctx->busy ? NGX_AGAIN : NGX_OK;
> + if (ctx->busy) {
> + if (in == NULL) {
> + return ngx_http_next_body_filter(r, NULL);
> + }
> +
> + return NGX_AGAIN;
> + }
> +
> + return NGX_OK;
> }
>
> if (!ctx->gzheader) {
If a write event is going to trigger ngx_http_output_filter(r,
NULL), it means that the request was already finalized, and in
non-error case there should be last buffer already seen by gzip
filter, and hence either ctx->done set, or ctx->nomem case
triggered.
Could you please elaborate how do you see the problem? In 1.5.6
this probably can be triggered with incomplete upstream response,
which intentionally results in no last buffer send, but with such
responses nothing is guaranteed anyway. And I don't think there
are any legitimate ways to trigger it in 1.4.3.
--
Maxim Dounin
http://nginx.org/en/donation.html
More information about the nginx-devel
mailing list