From 04545cb2b718286aa917d5aa80579fff305caf06 Mon Sep 17 00:00:00 2001 From: Aurelien DARRAGON Date: Mon, 12 Jan 2026 16:57:59 +0100 Subject: [PATCH] BUG/MINOR: hlua_fcn: fix broken yield for Patref:add_bulk() In GH #3241, GH user @kanashimia reported that the Patref:add_bulk() method would raise a Lua exception when called with more than 101 elements at once. As identified by @kanashimia there was an error in the way the add_bulk() method was forced to yield after 101 elements precisely. The yield is there to ensure Lua doesn't eat too much ressources at once and doesn't impact haproxy's core responsiveness, but the check for the yield was misplaced resulting in improper stack content upon resume. Thanks to user @kanashimia who even provided a reproducer which helped a lot to troubleshoot the issue. This fix should be backported up to 3.2 with 884dc62 ("MINOR: hlua_fcn: add Patref:add_bulk()") where the bug was introduced. --- src/hlua_fcn.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/hlua_fcn.c b/src/hlua_fcn.c index c6267f3ca..5026e30be 100644 --- a/src/hlua_fcn.c +++ b/src/hlua_fcn.c @@ -2808,17 +2808,6 @@ static int _hlua_patref_add_bulk(lua_State *L, int status, lua_KContext ctx) const char *key; const char *value = NULL; - /* check if we may do something to try to prevent thread contention, - * unless we run from body/init state where hlua_yieldk is no-op - */ - if (count > 100 && hlua_gethlua(L)) { - /* let's yield and wait for being called again to continue where we left off */ - HA_RWLOCK_WRUNLOCK(PATREF_LOCK, &ref->ptr->lock); - hlua_yieldk(L, 0, 0, _hlua_patref_add_bulk, TICK_ETERNITY, HLUA_CTRLYIELD); // continue - return 0; // not reached - - } - if (ref->ptr->flags & PAT_REF_SMP) { /* key:val table */ luaL_checktype(L, -2, LUA_TSTRING); @@ -2843,6 +2832,17 @@ static int _hlua_patref_add_bulk(lua_State *L, int status, lua_KContext ctx) /* removes 'value'; keeps 'key' for next iteration */ lua_pop(L, 1); count += 1; + + /* check if we may do something to try to prevent thread contention, + * unless we run from body/init state where hlua_yieldk is no-op + */ + if (count > 100 && hlua_gethlua(L)) { + /* let's yield and wait for being called again to continue where we left off */ + HA_RWLOCK_WRUNLOCK(PATREF_LOCK, &ref->ptr->lock); + hlua_yieldk(L, 0, 0, _hlua_patref_add_bulk, TICK_ETERNITY, HLUA_CTRLYIELD); // continue + return 0; // not reached + + } } HA_RWLOCK_WRUNLOCK(PATREF_LOCK, &ref->ptr->lock); lua_pushboolean(L, 1);