From: Aurelien DARRAGON Date: Wed, 11 Dec 2024 09:42:11 +0000 (+0100) Subject: BUG/MINOR: hlua_fcn: restore server pairs iterator pointer consistency X-Git-Tag: v3.0.12~117 X-Git-Url: http://git.haproxy.org/?a=commitdiff_plain;h=c24e7be8e2d1298c437f71f97879dbb78ec080d6;p=haproxy-3.0.git BUG/MINOR: hlua_fcn: restore server pairs iterator pointer consistency 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. (cherry picked from commit 358166ae6a3e98d36b378c7eeab1673cc8b4a4dd) Signed-off-by: Willy Tarreau (cherry picked from commit d3fd2a825b4520cc76584709123bdc6b781ab93f) Signed-off-by: Aurelien DARRAGON --- diff --git a/include/haproxy/hlua-t.h b/include/haproxy/hlua-t.h index bbbc61f..a98afa8 100644 --- a/include/haproxy/hlua-t.h +++ b/include/haproxy/hlua-t.h @@ -228,8 +228,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 */ }; #else /* USE_LUA */ diff --git a/src/hlua_fcn.c b/src/hlua_fcn.c index 79f4c28..f5c28e5 100644 --- a/src/hlua_fcn.c +++ b/src/hlua_fcn.c @@ -1852,29 +1852,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; } @@ -1891,7 +1895,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;