From baf0924a504fccaffb43a5f1b673568f00411cf3 Mon Sep 17 00:00:00 2001 From: Christopher Faulet Date: Mon, 4 May 2026 08:47:58 +0200 Subject: [PATCH] BUG/MINOR: resolvers: Free new requester on error when linking a resolution If an error is triggered while the requester was allocated, it is not immediately released. It is not really a memory leak because the requester will be reused laster, on a next attempt, or released on deinit. For a do-resolv action, the requester is released with the stream. So no leak here. But it is probably not expected to keep a newly allocated requester in case of error. This patch could be backported as far as 2.6. --- src/resolvers.c | 34 +++++++++++++++++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-) diff --git a/src/resolvers.c b/src/resolvers.c index a151f6034..7049ca8d6 100644 --- a/src/resolvers.c +++ b/src/resolvers.c @@ -2103,6 +2103,7 @@ int resolv_link_resolution(void *requester, int requester_type, int requester_lo struct stream *stream = NULL; char **hostname_dn; int hostname_dn_len, query_type; + int req_was_new = 0; enter_resolver_code(); switch (requester_type) { @@ -2112,6 +2113,7 @@ int resolv_link_resolution(void *requester, int requester_type, int requester_lo if (!requester_locked) HA_SPIN_LOCK(SERVER_LOCK, &srv->lock); + req_was_new = !srv->resolv_requester; req = resolv_get_requester(&srv->resolv_requester, &srv->obj_type, snr_resolution_cb, @@ -2137,6 +2139,7 @@ int resolv_link_resolution(void *requester, int requester_type, int requester_lo case OBJ_TYPE_SRVRQ: srvrq = (struct resolv_srvrq *)requester; + req_was_new = !srvrq->requester; req = resolv_get_requester(&srvrq->requester, &srvrq->obj_type, snr_resolution_cb, @@ -2153,6 +2156,7 @@ int resolv_link_resolution(void *requester, int requester_type, int requester_lo case OBJ_TYPE_STREAM: stream = (struct stream *)requester; + req_was_new = !stream->resolv_ctx.requester; req = resolv_get_requester(&stream->resolv_ctx.requester, &stream->obj_type, act_resolution_cb, @@ -2174,6 +2178,7 @@ int resolv_link_resolution(void *requester, int requester_type, int requester_lo case OBJ_TYPE_ACME_RSLV: { struct acme_rslv *acme_rslv = (struct acme_rslv *)requester; + req_was_new = !acme_rslv->requester; req = resolv_get_requester(&acme_rslv->requester, &acme_rslv->obj_type, acme_rslv->success_cb, @@ -2203,9 +2208,36 @@ int resolv_link_resolution(void *requester, int requester_type, int requester_lo leave_resolver_code(); return 0; - err: +err: if (res && LIST_ISEMPTY(&res->requesters)) resolv_free_resolution(res); + if (req_was_new) { + switch (requester_type) { + case OBJ_TYPE_SERVER: + srv->resolv_requester = NULL; + pool_free(resolv_requester_pool, req); + break; + case OBJ_TYPE_SRVRQ: + srvrq->requester = NULL; + pool_free(resolv_requester_pool, req); + break; + case OBJ_TYPE_STREAM: + stream->resolv_ctx.requester = NULL; + pool_free(resolv_requester_pool, req); + break; +#if defined(HAVE_ACME) + case OBJ_TYPE_ACME_RSLV: { + struct acme_rslv *acme_rslv = (struct acme_rslv *)requester; + acme_rslv->requester = NULL; + pool_free(resolv_requester_pool, req); + break; + } +#endif + default: + break; + } + } + leave_resolver_code(); return -1; }