From b7dba9006243f65e66d85a3a29841262c1c5dfef Mon Sep 17 00:00:00 2001 From: Max Romanov Date: Wed, 23 Dec 2020 11:01:36 +0300 Subject: [PATCH] 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. --- docs/changes.xml | 7 +++++++ src/nxt_http_static.c | 23 ++++++++++++++++++++--- 2 files changed, 27 insertions(+), 3 deletions(-) diff --git a/docs/changes.xml b/docs/changes.xml index db7a2799..86bdc10a 100644 --- a/docs/changes.xml +++ b/docs/changes.xml @@ -61,6 +61,13 @@ had appeared in 1.19.0. + + +a memory leak occurring in the router process when serving a file larger than +128K; the bug had appeared in 1.13.0. + + + 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);