@@ -1401,68 +1401,64 @@ static void u_userdata(Info *info) { /* ... */
14011401 }
14021402 case UTAG_LLEVENTS:
14031403 {
1404- // Because we have an inner, wrapped table reference we need to reserve
1405- // the idx for the outer event handler first, since we saw it first.
1406- int reference = allocate_ref_idx (info);
1407-
1408- unpersist (info); /* ... handlers_tab */
1409- eris_checktype (info, -1 , LUA_TTABLE);
1410- // We need to add a ref to the table so it stays alive as long as LLEvents
1411- int tab_ref = lua_ref (info->L , -1 );
1412- LuaTable *listeners_tab = hvalue (luaA_toobject (info->L , -1 ));
1413- lua_pop (info->L , 1 ); /* ... */
1414-
1404+ // Create userdata with safe initial values FIRST to handle cycles
14151405 auto *llevents = (lua_LLEvents*)lua_newuserdatataggedwithmetatable (
14161406 info->L ,
14171407 sizeof (lua_LLEvents),
14181408 UTAG_LLEVENTS
14191409 );
14201410 /* ... llevents */
1421- llevents->listeners_tab_ref = tab_ref;
1422- llevents->listeners_tab = listeners_tab;
1411+ llevents->listeners_tab_ref = -1 ;
1412+ llevents->listeners_tab = nullptr ;
1413+
1414+ // Register immediately to handle cycles (listeners_tab may reference this)
1415+ registerobject (info);
1416+
1417+ // Unpersist listeners_tab and store ref IMMEDIATELY to prevent leaks
1418+ unpersist (info); /* ... llevents handlers_tab */
1419+ eris_checktype (info, -1 , LUA_TTABLE);
1420+ llevents->listeners_tab_ref = lua_ref (info->L , -1 );
1421+ llevents->listeners_tab = hvalue (luaA_toobject (info->L , -1 ));
1422+ lua_pop (info->L , 1 ); /* ... llevents */
14231423
1424- // Manually put the LLEvents in the references table at the correct reference index
1425- lua_pushvalue (info->L , -1 ); /* perms reftbl ... obj obj */
1426- lua_rawseti (info->L , REFTIDX, reference); /* perms reftbl ... obj */
14271424 break ;
14281425 }
14291426 case UTAG_LLTIMERS:
14301427 {
1431- // Because we have an inner, wrapped table reference we need to reserve
1432- // the idx for the outer timer manager first, since we saw it first.
1433- int reference = allocate_ref_idx (info);
1428+ // Create userdata with safe initial values FIRST to handle cycles
1429+ auto *lltimers = (lua_LLTimers*)lua_newuserdatataggedwithmetatable (
1430+ info->L ,
1431+ sizeof (lua_LLTimers),
1432+ UTAG_LLTIMERS
1433+ );
1434+ /* ... lltimers */
1435+ lltimers->timers_tab_ref = -1 ;
1436+ lltimers->llevents_ref = -1 ;
1437+ lltimers->timer_wrapper_ref = -1 ;
1438+ lltimers->timers_tab = nullptr ;
14341439
1435- unpersist (info); /* ... timers_tab */
1440+ // Register immediately to handle cycles (timer_wrapper has LLTimers as upvalue)
1441+ registerobject (info);
1442+
1443+ // Unpersist timers_tab and store ref IMMEDIATELY to prevent leaks
1444+ unpersist (info); /* ... lltimers timers_tab */
14361445 eris_checktype (info, -1 , LUA_TTABLE);
1437- // We need to add a ref to the table so it stays alive as long as LLTimers
1438- int tab_ref = lua_ref (info->L , -1 );
1439- LuaTable *timers_tab = hvalue (luaA_toobject (info->L , -1 ));
1440- lua_pop (info->L , 1 ); /* ... */
1446+ lltimers->timers_tab_ref = lua_ref (info->L , -1 );
1447+ lltimers->timers_tab = hvalue (luaA_toobject (info->L , -1 ));
1448+ lua_pop (info->L , 1 ); /* ... lltimers */
14411449
1442- unpersist (info); /* ... llevents */
1450+ // Unpersist llevents and store ref IMMEDIATELY
1451+ unpersist (info); /* ... lltimers llevents */
14431452 eris_checkuserdatatag (info, -1 , UTAG_LLEVENTS);
1444- int llevents_ref = lua_ref (info->L , -1 );
1445- lua_pop (info->L , 1 ); /* ... */
1453+ lltimers-> llevents_ref = lua_ref (info->L , -1 );
1454+ lua_pop (info->L , 1 ); /* ... lltimers */
14461455
1447- unpersist (info); /* ... timer_wrapper */
1456+ // Unpersist timer_wrapper and store ref IMMEDIATELY
1457+ unpersist (info); /* ... lltimers timer_wrapper */
14481458 eris_checktype (info, -1 , LUA_TFUNCTION);
1449- int timer_wrapper_ref = lua_ref (info->L , -1 );
1450- lua_pop (info->L , 1 ); /* ... */
1459+ lltimers-> timer_wrapper_ref = lua_ref (info->L , -1 );
1460+ lua_pop (info->L , 1 ); /* ... lltimers */
14511461
1452- auto *lltimers = (lua_LLTimers*)lua_newuserdatataggedwithmetatable (
1453- info->L ,
1454- sizeof (lua_LLTimers),
1455- UTAG_LLTIMERS
1456- );
1457- /* ... lltimers */
1458- lltimers->timers_tab_ref = tab_ref;
1459- lltimers->timers_tab = timers_tab;
1460- lltimers->llevents_ref = llevents_ref;
1461- lltimers->timer_wrapper_ref = timer_wrapper_ref;
1462-
1463- // Manually put the LLTimers in the references table at the correct reference index
1464- lua_pushvalue (info->L , -1 ); /* perms reftbl ... obj obj */
1465- lua_rawseti (info->L , REFTIDX, reference); /* perms reftbl ... obj */
14661462 break ;
14671463 }
14681464 default :
0 commit comments