From 2a7cf4f319fc276f4554a8f6364e6b1ba4eb2ded Mon Sep 17 00:00:00 2001 From: Roberto I Date: Sun, 11 Jan 2026 15:36:03 -0300 Subject: More effort in avoiding errors in finalizers Before calling a finalizer, Lua not only checks stack limits, but actually ensures that a minimum number of slots are already allocated for the call. (If it cannot ensure that, it postpones the finalizer.) That avoids finalizers not running due to memory errors that the programmer cannot control. --- testes/gc.lua | 42 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) (limited to 'testes/gc.lua') diff --git a/testes/gc.lua b/testes/gc.lua index 62713dac..e50d9029 100644 --- a/testes/gc.lua +++ b/testes/gc.lua @@ -707,4 +707,46 @@ end collectgarbage(oldmode) + +if T then + print("testing stack issues when calling finalizers") + + local X + local obj + + local function initobj () + X = false + obj = setmetatable({}, {__gc = function () X = true end}) + end + + local function loop (n) + if n > 0 then loop(n - 1) end + end + + -- should not try to call finalizer without a CallInfo available + initobj() + loop(20) -- ensure stack space + T.resetCI() -- remove extra CallInfos + T.alloccount(0) -- cannot allocate more CallInfos + obj = nil + collectgarbage() -- will not call finalizer + T.alloccount() + assert(X == false) + collectgarbage() -- now will call finalizer (it was still pending) + assert(X == true) + + -- should not try to call finalizer without stack space available + initobj() + loop(5) -- ensure enough CallInfos + T.reallocstack(0) -- remove extra stack slots + T.alloccount(0) -- cannot reallocate stack + obj = nil + collectgarbage() -- will not call finalizer + T.alloccount() + assert(X == false) + collectgarbage() -- now will call finalizer (it was still pending) + assert(X == true) +end + + print('OK') -- cgit v1.2.3-55-g6feb