comparison src/http/modules/ngx_http_gunzip_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
comparison
equal deleted inserted replaced
5875:d91b98232e4c 5876:973fded4f461
173 173
174 static ngx_int_t 174 static ngx_int_t
175 ngx_http_gunzip_body_filter(ngx_http_request_t *r, ngx_chain_t *in) 175 ngx_http_gunzip_body_filter(ngx_http_request_t *r, ngx_chain_t *in)
176 { 176 {
177 int rc; 177 int rc;
178 ngx_uint_t flush;
178 ngx_chain_t *cl; 179 ngx_chain_t *cl;
179 ngx_http_gunzip_ctx_t *ctx; 180 ngx_http_gunzip_ctx_t *ctx;
180 181
181 ctx = ngx_http_get_module_ctx(r, ngx_http_gunzip_filter_module); 182 ctx = ngx_http_get_module_ctx(r, ngx_http_gunzip_filter_module);
182 183
197 if (ngx_chain_add_copy(r->pool, &ctx->in, in) != NGX_OK) { 198 if (ngx_chain_add_copy(r->pool, &ctx->in, in) != NGX_OK) {
198 goto failed; 199 goto failed;
199 } 200 }
200 } 201 }
201 202
202 if (ctx->nomem || in == NULL) { 203 if (ctx->nomem) {
203 204
204 /* flush busy buffers */ 205 /* flush busy buffers */
205 206
206 if (ngx_http_next_body_filter(r, NULL) == NGX_ERROR) { 207 if (ngx_http_next_body_filter(r, NULL) == NGX_ERROR) {
207 goto failed; 208 goto failed;
210 cl = NULL; 211 cl = NULL;
211 212
212 ngx_chain_update_chains(r->pool, &ctx->free, &ctx->busy, &cl, 213 ngx_chain_update_chains(r->pool, &ctx->free, &ctx->busy, &cl,
213 (ngx_buf_tag_t) &ngx_http_gunzip_filter_module); 214 (ngx_buf_tag_t) &ngx_http_gunzip_filter_module);
214 ctx->nomem = 0; 215 ctx->nomem = 0;
216 flush = 0;
217
218 } else {
219 flush = ctx->busy ? 1 : 0;
215 } 220 }
216 221
217 for ( ;; ) { 222 for ( ;; ) {
218 223
219 /* cycle while we can write to a client */ 224 /* cycle while we can write to a client */
256 } 261 }
257 262
258 /* rc == NGX_AGAIN */ 263 /* rc == NGX_AGAIN */
259 } 264 }
260 265
261 if (ctx->out == NULL) { 266 if (ctx->out == NULL && !flush) {
262 return ctx->busy ? NGX_AGAIN : NGX_OK; 267 return ctx->busy ? NGX_AGAIN : NGX_OK;
263 } 268 }
264 269
265 rc = ngx_http_next_body_filter(r, ctx->out); 270 rc = ngx_http_next_body_filter(r, ctx->out);
266 271
274 279
275 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, 280 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
276 "gunzip out: %p", ctx->out); 281 "gunzip out: %p", ctx->out);
277 282
278 ctx->nomem = 0; 283 ctx->nomem = 0;
284 flush = 0;
279 285
280 if (ctx->done) { 286 if (ctx->done) {
281 return rc; 287 return rc;
282 } 288 }
283 } 289 }