comparison src/http/modules/ngx_http_gzip_filter_module.c @ 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 e491b26fa5a1
children f01ab2dbcfdc
comparison
equal deleted inserted replaced
5875:d91b98232e4c 5876:973fded4f461
314 314
315 static ngx_int_t 315 static ngx_int_t
316 ngx_http_gzip_body_filter(ngx_http_request_t *r, ngx_chain_t *in) 316 ngx_http_gzip_body_filter(ngx_http_request_t *r, ngx_chain_t *in)
317 { 317 {
318 int rc; 318 int rc;
319 ngx_uint_t flush;
319 ngx_chain_t *cl; 320 ngx_chain_t *cl;
320 ngx_http_gzip_ctx_t *ctx; 321 ngx_http_gzip_ctx_t *ctx;
321 322
322 ctx = ngx_http_get_module_ctx(r, ngx_http_gzip_filter_module); 323 ctx = ngx_http_get_module_ctx(r, ngx_http_gzip_filter_module);
323 324
370 } 371 }
371 372
372 r->connection->buffered |= NGX_HTTP_GZIP_BUFFERED; 373 r->connection->buffered |= NGX_HTTP_GZIP_BUFFERED;
373 } 374 }
374 375
375 if (ctx->nomem || in == NULL) { 376 if (ctx->nomem) {
376 377
377 /* flush busy buffers */ 378 /* flush busy buffers */
378 379
379 if (ngx_http_next_body_filter(r, NULL) == NGX_ERROR) { 380 if (ngx_http_next_body_filter(r, NULL) == NGX_ERROR) {
380 goto failed; 381 goto failed;
383 cl = NULL; 384 cl = NULL;
384 385
385 ngx_chain_update_chains(r->pool, &ctx->free, &ctx->busy, &cl, 386 ngx_chain_update_chains(r->pool, &ctx->free, &ctx->busy, &cl,
386 (ngx_buf_tag_t) &ngx_http_gzip_filter_module); 387 (ngx_buf_tag_t) &ngx_http_gzip_filter_module);
387 ctx->nomem = 0; 388 ctx->nomem = 0;
389 flush = 0;
390
391 } else {
392 flush = ctx->busy ? 1 : 0;
388 } 393 }
389 394
390 for ( ;; ) { 395 for ( ;; ) {
391 396
392 /* cycle while we can write to a client */ 397 /* cycle while we can write to a client */
430 } 435 }
431 436
432 /* rc == NGX_AGAIN */ 437 /* rc == NGX_AGAIN */
433 } 438 }
434 439
435 if (ctx->out == NULL) { 440 if (ctx->out == NULL && !flush) {
436 ngx_http_gzip_filter_free_copy_buf(r, ctx); 441 ngx_http_gzip_filter_free_copy_buf(r, ctx);
437 442
438 return ctx->busy ? NGX_AGAIN : NGX_OK; 443 return ctx->busy ? NGX_AGAIN : NGX_OK;
439 } 444 }
440 445
455 ngx_chain_update_chains(r->pool, &ctx->free, &ctx->busy, &ctx->out, 460 ngx_chain_update_chains(r->pool, &ctx->free, &ctx->busy, &ctx->out,
456 (ngx_buf_tag_t) &ngx_http_gzip_filter_module); 461 (ngx_buf_tag_t) &ngx_http_gzip_filter_module);
457 ctx->last_out = &ctx->out; 462 ctx->last_out = &ctx->out;
458 463
459 ctx->nomem = 0; 464 ctx->nomem = 0;
465 flush = 0;
460 466
461 if (ctx->done) { 467 if (ctx->done) {
462 return rc; 468 return rc;
463 } 469 }
464 } 470 }