Skip to content

Commit 8a8a71c

Browse files
committed
bugfix: ngx.flush() buffer could be recycled while still queued.
Buffer taken from ctx->free_bufs with tag and with size 0 would be returned to the ctx->free_bufs by ngx_chain_update_chains(). When reused, it results into memzeroing the flush flag and "zero size buf in writer t:1 r:0 f:0" alerts.
1 parent 1731f35 commit 8a8a71c

2 files changed

Lines changed: 15 additions & 4 deletions

File tree

‎src/ngx_http_lua_util.h‎

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -491,12 +491,24 @@ ngx_http_lua_get_flush_chain(ngx_http_request_t *r, ngx_http_lua_ctx_t *ctx)
491491
{
492492
ngx_chain_t *cl;
493493

494-
cl = ngx_http_lua_chain_get_free_buf(r->connection->log, r->pool,
495-
&ctx->free_bufs, 0);
494+
/*
495+
* The flush buf is deliberately NOT taken from ctx->free_bufs and
496+
* deliberately carries no tag. It is size 0 and ngx_buf_special(), so the
497+
* write filter keeps it queued. If tagged, ngx_chain_update_chains() would
498+
* return it to ctx->free_bufs, and reusing it from there memzeros the
499+
* flush flag away, resulting in "zero size buf in writer t:1 r:0 f:0".
500+
*/
501+
cl = ngx_alloc_chain_link(r->pool);
496502
if (cl == NULL) {
497503
return NULL;
498504
}
499505

506+
cl->buf = ngx_calloc_buf(r->pool);
507+
if (cl->buf == NULL) {
508+
return NULL;
509+
}
510+
511+
cl->next = NULL;
500512
cl->buf->flush = 1;
501513

502514
return cl;

‎t/056-flush.t‎

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,7 @@ hello, world
4141
hiya
4242
--- no_error_log
4343
[error]
44-
--- error_log
45-
lua reuse free buf chain, but reallocate memory because 5 >= 0
44+
[alert]
4645
--- skip_eval: 4:defined($ENV{MOCKEAGAIN}) && ($ENV{MOCKEAGAIN} =~ /w/)
4746

4847

0 commit comments

Comments
 (0)