diff --git a/docs/changes.xml b/docs/changes.xml
index 569e49e5..f086e78f 100644
--- a/docs/changes.xml
+++ b/docs/changes.xml
@@ -45,6 +45,12 @@ this allows to do './configure && make && sudo make install'.
+
+
+fix the memory leak related to njs.
+
+
+
tstr_state);
+
return NXT_OK;
+
+fail:
+
+ nxt_tstr_state_release(vldt->tstr_state);
+
+ return ret;
}
diff --git a/src/nxt_http_request.c b/src/nxt_http_request.c
index 73ffd2f0..e78975aa 100644
--- a/src/nxt_http_request.c
+++ b/src/nxt_http_request.c
@@ -833,6 +833,10 @@ nxt_http_request_close_handler(nxt_task_t *task, void *obj, void *data)
r->body->file->fd = -1;
}
+ if (r->tstr_query != NULL) {
+ nxt_tstr_query_release(r->tstr_query);
+ }
+
if (nxt_fast_path(proto.any != NULL)) {
protocol = r->protocol;
diff --git a/src/nxt_js.c b/src/nxt_js.c
index aa3c4af5..4327e848 100644
--- a/src/nxt_js.c
+++ b/src/nxt_js.c
@@ -46,6 +46,7 @@ nxt_js_conf_new(nxt_mp_t *mp)
jcf->funcs = nxt_array_create(mp, 4, sizeof(nxt_str_t));
if (nxt_slow_path(jcf->funcs == NULL)) {
+ njs_vm_destroy(jcf->vm);
return NULL;
}
@@ -53,6 +54,13 @@ nxt_js_conf_new(nxt_mp_t *mp)
}
+void
+nxt_js_conf_release(nxt_js_conf_t *jcf)
+{
+ njs_vm_destroy(jcf->vm);
+}
+
+
void
nxt_js_set_proto(nxt_js_conf_t *jcf, njs_external_t *proto, njs_uint_t n)
{
@@ -297,3 +305,12 @@ nxt_js_call(nxt_task_t *task, nxt_js_cache_t *cache, nxt_js_t *js,
return NXT_OK;
}
+
+
+void
+nxt_js_release(nxt_js_cache_t *cache)
+{
+ if (cache->vm != NULL) {
+ njs_vm_destroy(cache->vm);
+ }
+}
diff --git a/src/nxt_js.h b/src/nxt_js.h
index dea43fe3..74d041ca 100644
--- a/src/nxt_js.h
+++ b/src/nxt_js.h
@@ -22,12 +22,14 @@ typedef struct {
nxt_js_conf_t *nxt_js_conf_new(nxt_mp_t *mp);
+void nxt_js_conf_release(nxt_js_conf_t *jcf);
void nxt_js_set_proto(nxt_js_conf_t *jcf, njs_external_t *proto, nxt_uint_t n);
nxt_js_t *nxt_js_add_tpl(nxt_js_conf_t *jcf, nxt_str_t *str, nxt_bool_t strz);
nxt_int_t nxt_js_compile(nxt_js_conf_t *jcf);
nxt_int_t nxt_js_test(nxt_js_conf_t *jcf, nxt_str_t *str, u_char *error);
nxt_int_t nxt_js_call(nxt_task_t *task, nxt_js_cache_t *cache, nxt_js_t *js,
nxt_str_t *str, void *ctx);
+void nxt_js_release(nxt_js_cache_t *cache);
extern njs_int_t nxt_js_proto_id;
diff --git a/src/nxt_router.c b/src/nxt_router.c
index edc015c5..17f6c572 100644
--- a/src/nxt_router.c
+++ b/src/nxt_router.c
@@ -1111,6 +1111,10 @@ temp_fail:
fail:
+ if (rtcf->tstr_state != NULL) {
+ nxt_tstr_state_release(rtcf->tstr_state);
+ }
+
nxt_mp_destroy(mp);
return NULL;
@@ -3794,6 +3798,8 @@ nxt_router_conf_release(nxt_task_t *task, nxt_socket_conf_joint_t *joint)
nxt_router_access_log_release(task, lock, rtcf->access_log);
+ nxt_tstr_state_release(rtcf->tstr_state);
+
nxt_mp_thread_adopt(rtcf->mem_pool);
nxt_mp_destroy(rtcf->mem_pool);
diff --git a/src/nxt_tstr.c b/src/nxt_tstr.c
index fd01797c..fda585b8 100644
--- a/src/nxt_tstr.c
+++ b/src/nxt_tstr.c
@@ -194,6 +194,15 @@ nxt_tstr_state_done(nxt_tstr_state_t *state, u_char *error)
}
+void
+nxt_tstr_state_release(nxt_tstr_state_t *state)
+{
+#if (NXT_HAVE_NJS)
+ nxt_js_conf_release(state->jcf);
+#endif
+}
+
+
nxt_bool_t
nxt_tstr_is_const(nxt_tstr_t *tstr)
{
@@ -315,3 +324,12 @@ nxt_tstr_query_handle(nxt_task_t *task, nxt_tstr_query_t *query,
task, query->ctx, query->data);
}
}
+
+
+void
+nxt_tstr_query_release(nxt_tstr_query_t *query)
+{
+#if (NXT_HAVE_NJS)
+ nxt_js_release(&query->cache->js);
+#endif
+}
diff --git a/src/nxt_tstr.h b/src/nxt_tstr.h
index 0cc24292..ce8e6f3a 100644
--- a/src/nxt_tstr.h
+++ b/src/nxt_tstr.h
@@ -42,6 +42,7 @@ nxt_tstr_t *nxt_tstr_compile(nxt_tstr_state_t *state, nxt_str_t *str,
nxt_tstr_flags_t flags);
nxt_int_t nxt_tstr_test(nxt_tstr_state_t *state, nxt_str_t *str, u_char *error);
nxt_int_t nxt_tstr_state_done(nxt_tstr_state_t *state, u_char *error);
+void nxt_tstr_state_release(nxt_tstr_state_t *state);
nxt_bool_t nxt_tstr_is_const(nxt_tstr_t *tstr);
void nxt_tstr_str(nxt_tstr_t *tstr, nxt_str_t *str);
@@ -55,6 +56,7 @@ void nxt_tstr_query_resolve(nxt_task_t *task, nxt_tstr_query_t *query,
void *data, nxt_work_handler_t ready, nxt_work_handler_t error);
void nxt_tstr_query_handle(nxt_task_t *task, nxt_tstr_query_t *query,
nxt_bool_t failed);
+void nxt_tstr_query_release(nxt_tstr_query_t *query);
nxt_inline nxt_bool_t