]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
BUG/MINOR: hlua_fcn: restore server pairs iterator pointer consistency
authorAurelien DARRAGON <adarragon@haproxy.com>
Wed, 11 Dec 2024 09:42:11 +0000 (10:42 +0100)
committerAurelien DARRAGON <adarragon@haproxy.com>
Wed, 11 Dec 2024 09:52:11 +0000 (10:52 +0100)
Since 9c91b30 ("MINOR: server: remove prev_deleted server list"), hlua
server pair iterator may use and return invalid (stale) server pointer
if multiple servers were deleted between two iterations.

Indeed, the server refcount mechanism (using srv_take()) is no longer
sufficient as the prev_deleted mitigation was removed.

To ensure server pointer consistency between two yields, the new watcher
mechanism must be used (as it already the case for stats dumping).

Thus in this patch we slightly change the server iteration logic:
hlua_server_list_iterator_context struct now stores the next valid server
pointer, and a watcher is added to ensure this pointer is never stale.

Then in hlua_listable_servers_pairs_iterator(), this next pointer is used
to create the Lua server object, and the next valid pointer is obtained by
leveraging watcher_next().

No backport needed unless 9c91b30 ("MINOR: server: remove prev_deleted
server list") is. Please note that dynamic servers were not supported in
Lua prior to 2.8, so it doesn't make sense to backport this patch further
than 2.8.

include/haproxy/hlua-t.h
src/hlua_fcn.c

index 397f1ccb827d03ec835cf4d7179cc48f191fa8ae..277586304d2015b2bad4a20ec77e65f7420ad5b0 100644 (file)
@@ -230,8 +230,11 @@ struct hlua_server_list {
 };
 
 struct hlua_server_list_iterator_context {
-       struct server *cur;
-       struct proxy *px;
+       struct watcher srv_watch; /* watcher to automatically update next pointer
+                                  * on server deletion
+                                  */
+       struct server *next;      /* next server in list */
+       struct proxy *px;         /* to retrieve first server */
 };
 
 #define HLUA_PATREF_FL_NONE    0x00
index e14004b65dd140b25e41fadc6e6d263ff612e27d..d49e073a46f6824e8f75b5b839573972b20f47c7 100644 (file)
@@ -1896,29 +1896,33 @@ int hlua_listable_servers_pairs_iterator(lua_State *L)
 {
        int context_index;
        struct hlua_server_list_iterator_context *ctx;
+       struct server *cur;
 
        context_index = lua_upvalueindex(1);
        ctx = lua_touserdata(L, context_index);
 
-       if (ctx->cur == NULL) {
+       if (ctx->px) {
                /* First iteration, initialize list on the first server */
-               ctx->cur = ctx->px->srv;
-       } else {
-
-               /* Next server (next ptr is always valid, even if current
-                * server has the SRV_F_DELETED flag set)
-                */
-               ctx->cur = ctx->cur->next;
+               cur = ctx->px->srv;
+               watcher_attach(&ctx->srv_watch, cur);
+               ctx->px = NULL;
+       }
+       else {
+               /* next iteration */
+               cur = ctx->next;
        }
 
-       /* next server is null, end of iteration */
-       if (ctx->cur == NULL) {
+       /* cur server is null, end of iteration */
+       if (cur == NULL) {
                lua_pushnil(L);
                return 1;
        }
 
-       lua_pushstring(L, ctx->cur->id);
-       hlua_fcn_new_server(L, ctx->cur);
+       /* compute next server */
+       ctx->next = watcher_next(&ctx->srv_watch, cur->next);
+
+       lua_pushstring(L, cur->id);
+       hlua_fcn_new_server(L, cur);
        return 2;
 }
 
@@ -1935,7 +1939,8 @@ int hlua_listable_servers_pairs(lua_State *L)
 
        ctx = lua_newuserdata(L, sizeof(*ctx));
        ctx->px = hlua_srv_list->px;
-       ctx->cur = NULL;
+       ctx->next = NULL;
+       watcher_init(&ctx->srv_watch, &ctx->next, offsetof(struct server, watcher_list));
 
        lua_pushcclosure(L, hlua_listable_servers_pairs_iterator, 1);
        return 1;