]> git.kaiwu.me - nginx.git/commitdiff
Gzip, gunzip: flush busy buffers if any.
authorMaxim Dounin <mdounin@mdounin.ru>
Wed, 15 Oct 2014 18:57:23 +0000 (22:57 +0400)
committerMaxim Dounin <mdounin@mdounin.ru>
Wed, 15 Oct 2014 18:57:23 +0000 (22:57 +0400)
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).

src/http/modules/ngx_http_gunzip_filter_module.c
src/http/modules/ngx_http_gzip_filter_module.c

index 70ec0aacea6c00e7a538482a184287a23c7ef469..c1341f56285f2ec31bfcbcd1f309f262d84a02cf 100644 (file)
@@ -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_request_t *r, ngx_chain_t *in)
         }
     }
 
-    if (ctx->nomem || in == NULL) {
+    if (ctx->nomem) {
 
         /* flush busy buffers */
 
@@ -212,6 +213,10 @@ ngx_http_gunzip_body_filter(ngx_http_request_t *r, ngx_chain_t *in)
         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_request_t *r, ngx_chain_t *in)
             /* 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_request_t *r, ngx_chain_t *in)
                        "gunzip out: %p", ctx->out);
 
         ctx->nomem = 0;
+        flush = 0;
 
         if (ctx->done) {
             return rc;
index c57a4a3c7cc2f0989c6f514ae7ac103e3807c175..f941e639735c849d842a2b9d73720998d56bfbb9 100644 (file)
@@ -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_request_t *r, ngx_chain_t *in)
         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_request_t *r, ngx_chain_t *in)
         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_request_t *r, ngx_chain_t *in)
             /* 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_request_t *r, ngx_chain_t *in)
         ctx->last_out = &ctx->out;
 
         ctx->nomem = 0;
+        flush = 0;
 
         if (ctx->done) {
             return rc;