Skip to main content

run_close_finalizers

Function run_close_finalizers 

Source
pub fn run_close_finalizers(state: &mut LuaState)
Expand description

Run every still-pending __gc finalizer at state close.

Mirrors C-Lua’s luaC_freeallobjects (lgc.c), which calls separatetobefnz(g, 1) to move all remaining finalizable objects (regardless of reachability) into the to-be-finalized list, then callallpendingfinalizers to invoke each __gc before the objects are freed. At lua_close, objects the program kept alive to program end — e.g. a table held by a global — still have their finalizer run; that is what emits messages like >>> closing state <<< from gc.lua.

Drains both queues until stable (issue #260 codex round 2, finding 3): the loop runs while either pending_finalizers or to_be_finalized is non-empty, so (a) leftovers parked in to_be_finalized by an earlier bounded incremental pass (run_some_pending_finalizers_inner caps at GC_FIN_MAX per step) still run at close even when pending is empty, and (b) a finalizer that registers a new finalizable object during the first pass has that object’s __gc run by a later pass. The seen set spans all passes, so each object identity is finalized at most once per close — a finalizer that re-registers its own object cannot loop the drain. seen is seeded with the identities already parked in to_be_finalized at entry — those objects are finalized by the first run_pending_finalizers call without ever passing through pending, and without the seed a self-re-registering queue-only finalizer would run twice (codex round-3 finding). (C refuses close-time registrations outright via GCSTPCLS; running fresh registrations exactly once is the deliberate divergence here, adjudicated on the #260 review.)