aboutsummaryrefslogtreecommitdiff
path: root/testes
diff options
context:
space:
mode:
authorRoberto I <roberto@inf.puc-rio.br>2026-01-11 15:36:03 -0300
committerRoberto I <roberto@inf.puc-rio.br>2026-01-11 15:36:03 -0300
commit2a7cf4f319fc276f4554a8f6364e6b1ba4eb2ded (patch)
treea99a8361664b0adda83186f04e2e9c98afd86b44 /testes
parent5cfc725a8b61a6f96c7324f60ac26739315095ba (diff)
downloadlua-2a7cf4f319fc276f4554a8f6364e6b1ba4eb2ded.tar.gz
lua-2a7cf4f319fc276f4554a8f6364e6b1ba4eb2ded.tar.bz2
lua-2a7cf4f319fc276f4554a8f6364e6b1ba4eb2ded.zip
More effort in avoiding errors in finalizersHEADmaster
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.
Diffstat (limited to '')
-rw-r--r--testes/gc.lua42
-rw-r--r--testes/memerr.lua19
-rw-r--r--testes/tracegc.lua9
3 files changed, 68 insertions, 2 deletions
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
707 707
708collectgarbage(oldmode) 708collectgarbage(oldmode)
709 709
710
711if T then
712 print("testing stack issues when calling finalizers")
713
714 local X
715 local obj
716
717 local function initobj ()
718 X = false
719 obj = setmetatable({}, {__gc = function () X = true end})
720 end
721
722 local function loop (n)
723 if n > 0 then loop(n - 1) end
724 end
725
726 -- should not try to call finalizer without a CallInfo available
727 initobj()
728 loop(20) -- ensure stack space
729 T.resetCI() -- remove extra CallInfos
730 T.alloccount(0) -- cannot allocate more CallInfos
731 obj = nil
732 collectgarbage() -- will not call finalizer
733 T.alloccount()
734 assert(X == false)
735 collectgarbage() -- now will call finalizer (it was still pending)
736 assert(X == true)
737
738 -- should not try to call finalizer without stack space available
739 initobj()
740 loop(5) -- ensure enough CallInfos
741 T.reallocstack(0) -- remove extra stack slots
742 T.alloccount(0) -- cannot reallocate stack
743 obj = nil
744 collectgarbage() -- will not call finalizer
745 T.alloccount()
746 assert(X == false)
747 collectgarbage() -- now will call finalizer (it was still pending)
748 assert(X == true)
749end
750
751
710print('OK') 752print('OK')
diff --git a/testes/memerr.lua b/testes/memerr.lua
index 9c940ca7..a55514a9 100644
--- a/testes/memerr.lua
+++ b/testes/memerr.lua
@@ -282,6 +282,25 @@ testamem("growing stack", function ()
282 return foo(100) 282 return foo(100)
283end) 283end)
284 284
285
286collectgarbage()
287collectgarbage()
288global io, T, setmetatable, collectgarbage, print
289
290local Count = 0
291testamem("finalizers", function ()
292 local X = false
293 local obj = setmetatable({}, {__gc = function () X = true end})
294 obj = nil
295 T.resetCI() -- remove extra CallInfos
296 T.reallocstack(18) -- remove extra stack slots
297 Count = Count + 1
298 io.stderr:write(Count, "\n")
299 T.trick(io)
300 collectgarbage()
301 return X
302end)
303
285-- }================================================================== 304-- }==================================================================
286 305
287 306
diff --git a/testes/tracegc.lua b/testes/tracegc.lua
index a8c929df..c1154f90 100644
--- a/testes/tracegc.lua
+++ b/testes/tracegc.lua
@@ -1,10 +1,15 @@
1-- track collections 1-- track collections
2 2
3
3local M = {} 4local M = {}
4 5
5-- import list 6-- import list
6local setmetatable, stderr, collectgarbage = 7local stderr, collectgarbage = io.stderr, collectgarbage
7 setmetatable, io.stderr, collectgarbage 8
9-- the debug version of setmetatable does not create any object (such as
10-- a '__metatable' string), and so it is more appropriate to be used in
11-- a finalizer
12local setmetatable = require"debug".setmetatable
8 13
9global none 14global none
10 15