summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorMax Romanov <max.romanov@nginx.com>2020-12-23 11:01:36 +0300
committerMax Romanov <max.romanov@nginx.com>2020-12-23 11:01:36 +0300
commitb7dba9006243f65e66d85a3a29841262c1c5dfef (patch)
treef36b8c60c0f573d3ac4949ae0aede586053e4524
parentcac762ab7ef22798d0f1d0813201c0018bd589a1 (diff)
downloadunit-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--docs/changes.xml7
-rw-r--r--src/nxt_http_static.c23
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.
</para>
</change>
+<change type="bugfix">
+<para>
+a memory leak occurring in the router process when serving a file larger than
+128K; the bug had appeared in 1.13.0.
+</para>
+</change>
+
</changes>
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);