Mercurial > hg > nginx
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 } |