mirror of
http://git.haproxy.org/git/haproxy.git/
synced 2025-01-21 13:02:55 +00:00
BUG/MINOR: hlua_fcn: restore server pairs iterator pointer consistency
Since9c91b30
("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 unless9c91b30
("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.
This commit is contained in:
parent
647a290662
commit
358166ae6a
@ -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
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user