]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
BUG/MINOR: hlua_fcn: fix broken yield for Patref:add_bulk()
authorAurelien DARRAGON <adarragon@haproxy.com>
Mon, 12 Jan 2026 15:57:59 +0000 (16:57 +0100)
committerAurelien DARRAGON <adarragon@haproxy.com>
Mon, 12 Jan 2026 16:30:52 +0000 (17:30 +0100)
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

index c6267f3ca2a944fd73861dbef5d80ac64ae11181..5026e30be159e9102ad7b8d3e80a64988f1541c0 100644 (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);