[nginx] Limit conn: fixed counter leak on memory allocation errors.
Maxim Dounin
mdounin at mdounin.ru
Mon Jul 7 04:29:40 UTC 2025
details: http://freenginx.org/hg/nginx/rev/722e252fcabe
branches:
changeset: 9389:722e252fcabe
user: Maxim Dounin <mdounin at mdounin.ru>
date: Mon Jul 07 04:34:18 2025 +0300
description:
Limit conn: fixed counter leak on memory allocation errors.
Previously, if ngx_pool_cleanup_add() failed, already incremented connection
counter was left as is, eventually resulting in unexpected connection
limiting or shared memory exhaustion. Fix is to decrement the counter
by calling the cleanup handler with data on stack.
diffstat:
src/http/modules/ngx_http_limit_conn_module.c | 16 ++++++++++++++++
src/stream/ngx_stream_limit_conn_module.c | 16 ++++++++++++++++
2 files changed, 32 insertions(+), 0 deletions(-)
diffs (80 lines):
diff --git a/src/http/modules/ngx_http_limit_conn_module.c b/src/http/modules/ngx_http_limit_conn_module.c
--- a/src/http/modules/ngx_http_limit_conn_module.c
+++ b/src/http/modules/ngx_http_limit_conn_module.c
@@ -60,6 +60,8 @@ static ngx_rbtree_node_t *ngx_http_limit
ngx_str_t *key, uint32_t hash);
static void ngx_http_limit_conn_cleanup(void *data);
static ngx_inline void ngx_http_limit_conn_cleanup_all(ngx_pool_t *pool);
+static void ngx_http_limit_conn_cleanup_node(ngx_shm_zone_t *shm_zone,
+ ngx_rbtree_node_t *node);
static ngx_int_t ngx_http_limit_conn_status_variable(ngx_http_request_t *r,
ngx_http_variable_value_t *v, uintptr_t data);
@@ -294,6 +296,7 @@ ngx_http_limit_conn_handler(ngx_http_req
cln = ngx_pool_cleanup_add(r->pool,
sizeof(ngx_http_limit_conn_cleanup_t));
if (cln == NULL) {
+ ngx_http_limit_conn_cleanup_node(limits[i].shm_zone, node);
return NGX_HTTP_INTERNAL_SERVER_ERROR;
}
@@ -433,6 +436,19 @@ ngx_http_limit_conn_cleanup_all(ngx_pool
}
+static void
+ngx_http_limit_conn_cleanup_node(ngx_shm_zone_t *shm_zone,
+ ngx_rbtree_node_t *node)
+{
+ ngx_http_limit_conn_cleanup_t lccln;
+
+ lccln.shm_zone = shm_zone;
+ lccln.node = node;
+
+ ngx_http_limit_conn_cleanup(&lccln);
+}
+
+
static ngx_int_t
ngx_http_limit_conn_init_zone(ngx_shm_zone_t *shm_zone, void *data)
{
diff --git a/src/stream/ngx_stream_limit_conn_module.c b/src/stream/ngx_stream_limit_conn_module.c
--- a/src/stream/ngx_stream_limit_conn_module.c
+++ b/src/stream/ngx_stream_limit_conn_module.c
@@ -59,6 +59,8 @@ static ngx_rbtree_node_t *ngx_stream_lim
ngx_str_t *key, uint32_t hash);
static void ngx_stream_limit_conn_cleanup(void *data);
static ngx_inline void ngx_stream_limit_conn_cleanup_all(ngx_pool_t *pool);
+static void ngx_stream_limit_conn_cleanup_node(ngx_shm_zone_t *shm_zone,
+ ngx_rbtree_node_t *node);
static ngx_int_t ngx_stream_limit_conn_status_variable(ngx_stream_session_t *s,
ngx_stream_variable_value_t *v, uintptr_t data);
@@ -274,6 +276,7 @@ ngx_stream_limit_conn_handler(ngx_stream
cln = ngx_pool_cleanup_add(s->connection->pool,
sizeof(ngx_stream_limit_conn_cleanup_t));
if (cln == NULL) {
+ ngx_stream_limit_conn_cleanup_node(limits[i].shm_zone, node);
return NGX_ERROR;
}
@@ -414,6 +417,19 @@ ngx_stream_limit_conn_cleanup_all(ngx_po
}
+static void
+ngx_stream_limit_conn_cleanup_node(ngx_shm_zone_t *shm_zone,
+ ngx_rbtree_node_t *node)
+{
+ ngx_stream_limit_conn_cleanup_t lccln;
+
+ lccln.shm_zone = shm_zone;
+ lccln.node = node;
+
+ ngx_stream_limit_conn_cleanup(&lccln);
+}
+
+
static ngx_int_t
ngx_stream_limit_conn_init_zone(ngx_shm_zone_t *shm_zone, void *data)
{
More information about the nginx-devel
mailing list