changeset 5876:973fded4f461

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).
author Maxim Dounin <mdounin@mdounin.ru>
date Wed, 15 Oct 2014 22:57:23 +0400
parents d91b98232e4c
children 60fde1bc7236
files src/http/modules/ngx_http_gunzip_filter_module.c src/http/modules/ngx_http_gzip_filter_module.c
diffstat 2 files changed, 16 insertions(+), 4 deletions(-) [+]
line wrap: on
line diff
--- a/src/http/modules/ngx_http_gunzip_filter_module.c	Tue Oct 14 20:19:36 2014 +0400
+++ b/src/http/modules/ngx_http_gunzip_filter_module.c	Wed Oct 15 22:57:23 2014 +0400
@@ -175,6 +175,7 @@
 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 @@
         }
     }
 
-    if (ctx->nomem || in == NULL) {
+    if (ctx->nomem) {
 
         /* flush busy buffers */
 
@@ -212,6 +213,10 @@
         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 @@
             /* rc == NGX_AGAIN */
         }
 
-        if (ctx->out == NULL) {
+        if (ctx->out == NULL && !flush) {
             return ctx->busy ? NGX_AGAIN : NGX_OK;
         }
 
@@ -276,6 +281,7 @@
                        "gunzip out: %p", ctx->out);
 
         ctx->nomem = 0;
+        flush = 0;
 
         if (ctx->done) {
             return rc;
--- a/src/http/modules/ngx_http_gzip_filter_module.c	Tue Oct 14 20:19:36 2014 +0400
+++ b/src/http/modules/ngx_http_gzip_filter_module.c	Wed Oct 15 22:57:23 2014 +0400
@@ -316,6 +316,7 @@
 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 @@
         r->connection->buffered |= NGX_HTTP_GZIP_BUFFERED;
     }
 
-    if (ctx->nomem || in == NULL) {
+    if (ctx->nomem) {
 
         /* flush busy buffers */
 
@@ -385,6 +386,10 @@
         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 @@
             /* 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 @@
         ctx->last_out = &ctx->out;
 
         ctx->nomem = 0;
+        flush = 0;
 
         if (ctx->done) {
             return rc;