diff options
author | Max Romanov <max.romanov@nginx.com> | 2020-12-23 11:01:36 +0300 |
---|---|---|
committer | Max Romanov <max.romanov@nginx.com> | 2020-12-23 11:01:36 +0300 |
commit | b7dba9006243f65e66d85a3a29841262c1c5dfef (patch) | |
tree | f36b8c60c0f573d3ac4949ae0aede586053e4524 /src | |
parent | cac762ab7ef22798d0f1d0813201c0018bd589a1 (diff) | |
download | unit-b7dba9006243f65e66d85a3a29841262c1c5dfef.tar.gz unit-b7dba9006243f65e66d85a3a29841262c1c5dfef.tar.bz2 |
Static: fixing request memory pool leakage in router.
When a static file larger than NXT_HTTP_STATIC_BUF_SIZE (128K) is served, two
buffers are allocated and chained; each retains the whole request memory pool.
Starting from 41331471eee7, the completion handler was called once for a linked
buffer chain, but the second buffer got lost.
This patch improves the completion handler's treatment of static buffers to
handle all linked buffers.
Diffstat (limited to '')
-rw-r--r-- | src/nxt_http_static.c | 23 |
1 files changed, 20 insertions, 3 deletions
diff --git a/src/nxt_http_static.c b/src/nxt_http_static.c index 5687ef2c..df2655fc 100644 --- a/src/nxt_http_static.c +++ b/src/nxt_http_static.c @@ -395,12 +395,15 @@ static void nxt_http_static_buf_completion(nxt_task_t *task, void *obj, void *data) { ssize_t n, size; - nxt_buf_t *b, *fb; + nxt_buf_t *b, *fb, *next; nxt_off_t rest; nxt_http_request_t *r; b = obj; r = data; + +complete_buf: + fb = r->out; if (nxt_slow_path(fb == NULL || r->error)) { @@ -424,6 +427,8 @@ nxt_http_static_buf_completion(nxt_task_t *task, void *obj, void *data) goto clean; } + next = b->next; + if (n == rest) { nxt_file_close(task, fb->file); r->out = NULL; @@ -439,12 +444,24 @@ nxt_http_static_buf_completion(nxt_task_t *task, void *obj, void *data) b->mem.free = b->mem.pos + n; nxt_http_request_send(task, r, b); + + if (next != NULL) { + b = next; + goto complete_buf; + } + return; clean: - nxt_mp_free(r->mem_pool, b); - nxt_mp_release(r->mem_pool); + do { + next = b->next; + + nxt_mp_free(r->mem_pool, b); + nxt_mp_release(r->mem_pool); + + b = next; + } while (b != NULL); if (fb != NULL) { nxt_file_close(task, fb->file); |