Mercurial > njs
changeset 2561:96ec59c0cfc4
QuickJS: added memory limit check for reuse queue.
| author | Dmitry Volyntsev <xeioex@nginx.com> |
|---|---|
| date | Wed, 21 May 2025 17:10:15 -0700 |
| parents | f607fb929ffb |
| children | f114be6952f9 |
| files | nginx/ngx_http_js_module.c nginx/ngx_js.c nginx/ngx_js.h nginx/ngx_stream_js_module.c |
| diffstat | 4 files changed, 41 insertions(+), 0 deletions(-) [+] |
line wrap: on
line diff
--- a/nginx/ngx_http_js_module.c Wed May 14 18:16:15 2025 -0700 +++ b/nginx/ngx_http_js_module.c Wed May 21 17:10:15 2025 -0700 @@ -433,6 +433,13 @@ offsetof(ngx_http_js_loc_conf_t, reuse), NULL }, + { ngx_string("js_context_reuse_max_size"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, + ngx_conf_set_size_slot, + NGX_HTTP_LOC_CONF_OFFSET, + offsetof(ngx_http_js_loc_conf_t, reuse_max_size), + NULL }, + { ngx_string("js_import"), NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE13, ngx_js_import,
--- a/nginx/ngx_js.c Wed May 14 18:16:15 2025 -0700 +++ b/nginx/ngx_js.c Wed May 21 17:10:15 2025 -0700 @@ -1133,6 +1133,7 @@ JSRuntime *rt; JSContext *cx; JSClassID class_id; + JSMemoryUsage stats; ngx_qjs_event_t *event; ngx_js_opaque_t *opaque; njs_rbtree_node_t *node; @@ -1198,6 +1199,28 @@ cln->data = conf->reuse_queue; } + /* + * After the request object is freed, the runtime's memory usage should + * be low. It can only remain high if the global scope was + * modified. + * + * To prevent unlimited memory consumption growth, check whether memory + * usage exceeds the configured limit. The check is performed rarely to + * avoid performance impact of JS_ComputeMemoryUsage() which is slow. + */ + + if ((ngx_random() & 0xff) == 1) { + JS_ComputeMemoryUsage(JS_GetRuntime(cx), &stats); + + if ((size_t) stats.malloc_size > conf->reuse_max_size) { + ngx_log_error(NGX_LOG_WARN, ctx->log, 0, + "js remaining memory usage of the context " + "exceeds \"js_context_reuse_max_size\" limit: %L" + ", not reusing it", stats.malloc_size); + goto free_ctx; + } + } + if (ngx_js_queue_push(conf->reuse_queue, cx) != NGX_OK) { goto free_ctx; } @@ -3950,6 +3973,7 @@ conf->preload_objects = NGX_CONF_UNSET_PTR; conf->reuse = NGX_CONF_UNSET_SIZE; + conf->reuse_max_size = NGX_CONF_UNSET_SIZE; conf->buffer_size = NGX_CONF_UNSET_SIZE; conf->max_response_body_size = NGX_CONF_UNSET_SIZE; conf->timeout = NGX_CONF_UNSET_MSEC; @@ -4059,6 +4083,8 @@ ngx_conf_merge_msec_value(conf->timeout, prev->timeout, 60000); ngx_conf_merge_size_value(conf->reuse, prev->reuse, 128); + ngx_conf_merge_size_value(conf->reuse_max_size, prev->reuse_max_size, + 4 * 1024 * 1024); ngx_conf_merge_size_value(conf->buffer_size, prev->buffer_size, 16384); ngx_conf_merge_size_value(conf->max_response_body_size, prev->max_response_body_size, 1048576);
--- a/nginx/ngx_js.h Wed May 14 18:16:15 2025 -0700 +++ b/nginx/ngx_js.h Wed May 21 17:10:15 2025 -0700 @@ -122,6 +122,7 @@ ngx_uint_t type; \ ngx_engine_t *engine; \ ngx_uint_t reuse; \ + size_t reuse_max_size; \ ngx_js_queue_t *reuse_queue; \ ngx_str_t cwd; \ ngx_array_t *imports; \
--- a/nginx/ngx_stream_js_module.c Wed May 14 18:16:15 2025 -0700 +++ b/nginx/ngx_stream_js_module.c Wed May 21 17:10:15 2025 -0700 @@ -264,6 +264,13 @@ offsetof(ngx_stream_js_srv_conf_t, reuse), NULL }, + { ngx_string("js_context_reuse_max_size"), + NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1, + ngx_conf_set_size_slot, + NGX_STREAM_SRV_CONF_OFFSET, + offsetof(ngx_stream_js_srv_conf_t, reuse_max_size), + NULL }, + { ngx_string("js_import"), NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE13, ngx_js_import,
