]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: lua: use watcher for proxies iterator
authorAmaury Denoyelle <adenoyelle@haproxy.com>
Tue, 24 Feb 2026 16:47:46 +0000 (17:47 +0100)
committerAmaury Denoyelle <adenoyelle@haproxy.com>
Mon, 2 Mar 2026 09:36:21 +0000 (10:36 +0100)
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
src/hlua_fcn.c

index ac0b7d541a05586ede52b421c640f76a31f0b421..16d9bead51576f8af2cac8de6c1c05e9256b0228 100644 (file)
@@ -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;
 };
index 6fc0d5d8bb4eafbd1a3f7dd3ecbab550d9b9cac4..0566c886435b478565366584b8a7716fd1bd7f5c 100644 (file)
@@ -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;
 }