Welcome! Log In Create A New Profile

Advanced

[nginx] Gzip, gunzip: flush busy buffers if any.

Maxim Dounin
October 15, 2014 03:00PM
details: http://hg.nginx.org/nginx/rev/973fded4f461
branches:
changeset: 5876:973fded4f461
user: Maxim Dounin <mdounin@mdounin.ru>
date: Wed Oct 15 22:57:23 2014 +0400
description:
Gzip, gunzip: flush busy buffers if any.

Previous code resulted in transfer stalls when client happened
to read all the data in buffers at once, while all gzip buffers
were exhausted (but ctx->nomem wasn't set). Make sure to call
next body filter at least once per call if there are busy buffers.

Additionally, handling of calls with NULL chain was changed to follow
the same logic, i.e., next body filter is only called with NULL chain
if there are busy buffers. This is expected to fix "output chain is empty"
alerts as reported by some users after c52a761a2029 (1.5.7).

diffstat:

src/http/modules/ngx_http_gunzip_filter_module.c | 10 ++++++++--
src/http/modules/ngx_http_gzip_filter_module.c | 10 ++++++++--
2 files changed, 16 insertions(+), 4 deletions(-)

diffs (96 lines):

diff --git a/src/http/modules/ngx_http_gunzip_filter_module.c b/src/http/modules/ngx_http_gunzip_filter_module.c
--- a/src/http/modules/ngx_http_gunzip_filter_module.c
+++ b/src/http/modules/ngx_http_gunzip_filter_module.c
@@ -175,6 +175,7 @@ static ngx_int_t
ngx_http_gunzip_body_filter(ngx_http_request_t *r, ngx_chain_t *in)
{
int rc;
+ ngx_uint_t flush;
ngx_chain_t *cl;
ngx_http_gunzip_ctx_t *ctx;

@@ -199,7 +200,7 @@ ngx_http_gunzip_body_filter(ngx_http_req
}
}

- if (ctx->nomem || in == NULL) {
+ if (ctx->nomem) {

/* flush busy buffers */

@@ -212,6 +213,10 @@ ngx_http_gunzip_body_filter(ngx_http_req
ngx_chain_update_chains(r->pool, &ctx->free, &ctx->busy, &cl,
(ngx_buf_tag_t) &ngx_http_gunzip_filter_module);
ctx->nomem = 0;
+ flush = 0;
+
+ } else {
+ flush = ctx->busy ? 1 : 0;
}

for ( ;; ) {
@@ -258,7 +263,7 @@ ngx_http_gunzip_body_filter(ngx_http_req
/* rc == NGX_AGAIN */
}

- if (ctx->out == NULL) {
+ if (ctx->out == NULL && !flush) {
return ctx->busy ? NGX_AGAIN : NGX_OK;
}

@@ -276,6 +281,7 @@ ngx_http_gunzip_body_filter(ngx_http_req
"gunzip out: %p", ctx->out);

ctx->nomem = 0;
+ flush = 0;

if (ctx->done) {
return rc;
diff --git a/src/http/modules/ngx_http_gzip_filter_module.c b/src/http/modules/ngx_http_gzip_filter_module.c
--- a/src/http/modules/ngx_http_gzip_filter_module.c
+++ b/src/http/modules/ngx_http_gzip_filter_module.c
@@ -316,6 +316,7 @@ static ngx_int_t
ngx_http_gzip_body_filter(ngx_http_request_t *r, ngx_chain_t *in)
{
int rc;
+ ngx_uint_t flush;
ngx_chain_t *cl;
ngx_http_gzip_ctx_t *ctx;

@@ -372,7 +373,7 @@ ngx_http_gzip_body_filter(ngx_http_reque
r->connection->buffered |= NGX_HTTP_GZIP_BUFFERED;
}

- if (ctx->nomem || in == NULL) {
+ if (ctx->nomem) {

/* flush busy buffers */

@@ -385,6 +386,10 @@ ngx_http_gzip_body_filter(ngx_http_reque
ngx_chain_update_chains(r->pool, &ctx->free, &ctx->busy, &cl,
(ngx_buf_tag_t) &ngx_http_gzip_filter_module);
ctx->nomem = 0;
+ flush = 0;
+
+ } else {
+ flush = ctx->busy ? 1 : 0;
}

for ( ;; ) {
@@ -432,7 +437,7 @@ ngx_http_gzip_body_filter(ngx_http_reque
/* rc == NGX_AGAIN */
}

- if (ctx->out == NULL) {
+ if (ctx->out == NULL && !flush) {
ngx_http_gzip_filter_free_copy_buf(r, ctx);

return ctx->busy ? NGX_AGAIN : NGX_OK;
@@ -457,6 +462,7 @@ ngx_http_gzip_body_filter(ngx_http_reque
ctx->last_out = &ctx->out;

ctx->nomem = 0;
+ flush = 0;

if (ctx->done) {
return rc;

_______________________________________________
nginx-devel mailing list
nginx-devel@nginx.org
http://mailman.nginx.org/mailman/listinfo/nginx-devel
Subject Author Views Posted

[nginx] Gzip, gunzip: flush busy buffers if any.

Maxim Dounin 800 October 15, 2014 03:00PM



Sorry, you do not have permission to post/reply in this forum.

Online Users

Guests: 160
Record Number of Users: 8 on April 13, 2023
Record Number of Guests: 500 on July 15, 2024
Powered by nginx      Powered by FreeBSD      PHP Powered      Powered by MariaDB      ipv6 ready