From ebbdfc5915855c599cfca598c0ad24cbf9bf61c3 Mon Sep 17 00:00:00 2001 From: Amaury Denoyelle Date: Tue, 24 Feb 2026 17:47:46 +0100 Subject: [PATCH] MINOR: lua: use watcher for proxies iterator Ensures proxies iteration via lua functions is safe via a new watcher member. The principle is similar to the one already used for servers iteration. --- include/haproxy/hlua-t.h | 1 + src/hlua_fcn.c | 36 ++++++++++++++++++++++++++++++++---- 2 files changed, 33 insertions(+), 4 deletions(-) diff --git a/include/haproxy/hlua-t.h b/include/haproxy/hlua-t.h index ac0b7d541..16d9bead5 100644 --- a/include/haproxy/hlua-t.h +++ b/include/haproxy/hlua-t.h @@ -222,6 +222,7 @@ struct hlua_proxy_list { }; struct hlua_proxy_list_iterator_context { + struct watcher px_watch; /* watcher to automatically update next pointer on backend deletion */ struct proxy *next; char capabilities; }; diff --git a/src/hlua_fcn.c b/src/hlua_fcn.c index 6fc0d5d8b..0566c8864 100644 --- a/src/hlua_fcn.c +++ b/src/hlua_fcn.c @@ -2316,13 +2316,30 @@ int hlua_listable_proxies_pairs_iterator(lua_State *L) lua_pushstring(L, ctx->next->id); hlua_fcn_new_proxy(L, ctx->next); - for (ctx->next = ctx->next->next; + ctx->next = watcher_next(&ctx->px_watch, ctx->next->next); + for (; ctx->next && !hlua_listable_proxies_match(ctx->next, ctx->capabilities); - ctx->next = ctx->next->next); + ctx->next = watcher_next(&ctx->px_watch, ctx->next->next)) + ; return 2; } +/* ensure proper cleanup for listable_proxies_pairs */ +int hlua_listable_proxies_pairs_gc(lua_State *L) +{ + struct hlua_proxy_list_iterator_context *ctx; + + ctx = lua_touserdata(L, 1); + + /* we need to make sure that the watcher leaves in detached state even + * if the iterator was interrupted (ie: "break" from the loop), else + * the server watcher list will become corrupted + */ + watcher_detach(&ctx->px_watch); + return 0; +} + /* init the iterator context, return iterator function * with context as closure. The only argument is a * proxy object. @@ -2336,10 +2353,21 @@ int hlua_listable_proxies_pairs(lua_State *L) ctx = lua_newuserdata(L, sizeof(*ctx)); + /* add gc metamethod to the newly created userdata */ + lua_newtable(L); + hlua_class_function(L, "__gc", hlua_listable_proxies_pairs_gc); + lua_setmetatable(L, -2); + ctx->capabilities = hlua_px->capabilities; - for (ctx->next = proxies_list; + + ctx->next = NULL; + watcher_init(&ctx->px_watch, &ctx->next, offsetof(struct proxy, watcher_list)); + + for (watcher_attach(&ctx->px_watch, proxies_list); ctx->next && !hlua_listable_proxies_match(ctx->next, ctx->capabilities); - ctx->next = ctx->next->next); + ctx->next = watcher_next(&ctx->px_watch, ctx->next->next)) + ; + lua_pushcclosure(L, hlua_listable_proxies_pairs_iterator, 1); return 1; }