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.
This commit is contained in:
Aurelien DARRAGON 2026-01-12 16:57:59 +01:00
parent b1cfeeef21
commit 04545cb2b7

View File

@ -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);