Permalink
Browse files

optimize: now we recycle the special flush buf and chain link for ngx…

….flush() to prevent request-scoped memory leaks when emitting long data streams to the downstream.
  • Loading branch information...
agentzh committed Mar 11, 2012
1 parent 58cd7f0 commit 04332d929d3900ca207315befd8db0bcf2f6af96
Showing with 72 additions and 18 deletions.
  1. +2 −0 src/ngx_http_lua_common.h
  2. +26 −10 src/ngx_http_lua_output.c
  3. +9 −4 src/ngx_http_lua_util.c
  4. +34 −4 t/056-flush.t
  5. +1 −0 util/build2.sh
@@ -153,6 +153,7 @@ typedef struct {
ngx_chain_t *free_bufs;
ngx_chain_t *busy_bufs;
ngx_chain_t *free_recv_bufs;
+ ngx_chain_t *flush_buf;
ngx_http_cleanup_pt *cleanup;
@@ -215,6 +216,7 @@ typedef struct {
unsigned socket_ready:1;
unsigned aborted:1;
+ unsigned buffering:1;
} ngx_http_lua_ctx_t;
View
@@ -464,20 +464,36 @@ ngx_http_lua_ngx_flush(lua_State *L)
return luaL_error(L, "already seen eof");
}
- buf = ngx_calloc_buf(r->pool);
- if (buf == NULL) {
- return luaL_error(L, "memory allocation error");
+ if (ctx->buffering) {
+ ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
+ "lua http 1.0 buffering makes ngx.flush() a no-op");
+
+ return 0;
}
- buf->flush = 1;
+ if (ctx->flush_buf) {
+ cl = ctx->flush_buf;
- cl = ngx_alloc_chain_link(r->pool);
- if (cl == NULL) {
- return luaL_error(L, "out of memory");
- }
+ } else {
+ dd("allocating new flush buf");
+ buf = ngx_calloc_buf(r->pool);
+ if (buf == NULL) {
+ return luaL_error(L, "memory allocation error");
+ }
- cl->next = NULL;
- cl->buf = buf;
+ buf->flush = 1;
+
+ dd("allocating new flush chain");
+ cl = ngx_alloc_chain_link(r->pool);
+ if (cl == NULL) {
+ return luaL_error(L, "out of memory");
+ }
+
+ cl->next = NULL;
+ cl->buf = buf;
+
+ ctx->flush_buf = cl;
+ }
rc = ngx_http_lua_send_chain_link(r, ctx, cl);
View
@@ -373,19 +373,24 @@ ngx_http_lua_send_chain_link(ngx_http_request_t *r, ngx_http_lua_ctx_t *ctx,
return rc;
}
+ if (!ctx->buffering && !ctx->headers_sent
+ && r->http_version < NGX_HTTP_VERSION_11)
+ {
+ ctx->buffering = 1;
+ }
+
if (r->header_only) {
ctx->eof = 1;
- if (!ctx->headers_sent && r->http_version < NGX_HTTP_VERSION_11)
- {
+ if (ctx->buffering) {
return ngx_http_lua_send_http10_headers(r, ctx);
}
return rc;
}
if (in == NULL) {
- if (!ctx->headers_sent && r->http_version < NGX_HTTP_VERSION_11) {
+ if (ctx->buffering) {
rc = ngx_http_lua_send_http10_headers(r, ctx);
if (rc == NGX_ERROR || rc >= NGX_HTTP_SPECIAL_RESPONSE) {
return rc;
@@ -427,7 +432,7 @@ ngx_http_lua_send_chain_link(ngx_http_request_t *r, ngx_http_lua_ctx_t *ctx,
/* in != NULL */
- if (r->http_version < NGX_HTTP_VERSION_11 && !ctx->headers_sent) {
+ if (ctx->buffering) {
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
"lua buffering output bufs for the HTTP 1.0 request");
View
@@ -14,7 +14,7 @@ use Test::Nginx::Socket;
repeat_each(2);
-plan tests => repeat_each() * (blocks() * 2 + 1);
+plan tests => repeat_each() * (blocks() * 2 + 5);
#no_diff();
#no_long_string();
@@ -95,25 +95,55 @@ hiya
-=== TEST 5: http 1.0
+=== TEST 5: http 1.0 (sync)
--- config
location /test {
content_by_lua '
ngx.say("hello, world")
ngx.flush(true)
ngx.say("hiya")
+ ngx.flush(true)
+ ngx.say("blah")
';
}
--- request
GET /test HTTP/1.0
--- response_body
hello, world
hiya
+blah
+--- timeout: 5
+--- error_log
+lua buffering output bufs for the HTTP 1.0 request
+lua http 1.0 buffering makes ngx.flush() a no-op
+
+
+
+=== TEST 6: http 1.0 (async)
+--- config
+ location /test {
+ content_by_lua '
+ ngx.say("hello, world")
+ ngx.flush(false)
+ ngx.say("hiya")
+ ngx.flush(false)
+ ngx.say("blah")
+ ';
+ }
+--- request
+GET /test HTTP/1.0
+--- response_body
+hello, world
+hiya
+blah
+--- error_log
+lua buffering output bufs for the HTTP 1.0 request
+lua http 1.0 buffering makes ngx.flush() a no-op
--- timeout: 5
-=== TEST 6: flush wait - big data
+=== TEST 7: flush wait - big data
--- config
location /test {
content_by_lua '
@@ -131,7 +161,7 @@ hiya
-=== TEST 7: flush wait - content
+=== TEST 8: flush wait - content
--- config
location /test {
content_by_lua '
View
@@ -19,6 +19,7 @@ force=$2
time ngx-build $force $version \
--with-cc-opt=$'-I/opt/pcre821jit/include' \
+ --with-http_realip_module \
--with-http_ssl_module \
--add-module=$root/../ndk-nginx-module \
--add-module=$root/../set-misc-nginx-module \

0 comments on commit 04332d9

Please sign in to comment.