No more LUA_ERRGCMM errors
Errors in finalizers (__gc metamethods) are never propagated. Instead, they generate a warning.
This commit is contained in:
@@ -190,12 +190,17 @@ assert(dofile('verybig.lua', true) == 10); collectgarbage()
|
||||
dofile('files.lua')
|
||||
|
||||
if #msgs > 0 then
|
||||
warn("*tests not performed:\n ")
|
||||
warn("#tests not performed:\n ")
|
||||
for i=1,#msgs do
|
||||
warn(msgs[i]); warn("\n ")
|
||||
end
|
||||
warn("\n")
|
||||
end
|
||||
|
||||
print("(there should be two warnings now)")
|
||||
warn("#This is "); warn("an expected"); warn(" warning\n")
|
||||
warn("#This is"); warn(" another one\n")
|
||||
|
||||
-- no test module should define 'debug'
|
||||
assert(debug == nil)
|
||||
|
||||
@@ -219,10 +224,6 @@ local _G, showmem, print, format, clock, time, difftime, assert, open =
|
||||
local fname = T and "time-debug.txt" or "time.txt"
|
||||
local lasttime
|
||||
|
||||
|
||||
warn("*This is "); warn("an expected"); warn(" warning\n")
|
||||
warn("*This is"); warn(" another one\n")
|
||||
|
||||
if not usertests then
|
||||
-- open file with time of last performed test
|
||||
local f = io.open(fname)
|
||||
|
||||
@@ -114,13 +114,12 @@ end
|
||||
|
||||
-- testing warnings
|
||||
T.testC([[
|
||||
warning "*This "
|
||||
warning "warning "
|
||||
warning "should be in a"
|
||||
warning " single line
|
||||
warning "#This shold be a"
|
||||
warning " single "
|
||||
warning "warning
|
||||
"
|
||||
warning "*This should be "
|
||||
warning "another warning
|
||||
warning "#This should be "
|
||||
warning "another one
|
||||
"
|
||||
]])
|
||||
|
||||
@@ -896,24 +895,15 @@ do -- testing errors during GC
|
||||
a[i] = T.newuserdata(i) -- creates several udata
|
||||
end
|
||||
for i=1,20,2 do -- mark half of them to raise errors during GC
|
||||
debug.setmetatable(a[i], {__gc = function (x) error("error inside gc") end})
|
||||
debug.setmetatable(a[i],
|
||||
{__gc = function (x) error("@expected error in gc") end})
|
||||
end
|
||||
for i=2,20,2 do -- mark the other half to count and to create more garbage
|
||||
debug.setmetatable(a[i], {__gc = function (x) load("A=A+1")() end})
|
||||
end
|
||||
a = nil
|
||||
_G.A = 0
|
||||
a = 0
|
||||
while 1 do
|
||||
local stat, msg = pcall(collectgarbage)
|
||||
if stat then
|
||||
break -- stop when no more errors
|
||||
else
|
||||
a = a + 1
|
||||
assert(string.find(msg, "__gc"))
|
||||
end
|
||||
end
|
||||
assert(a == 10) -- number of errors
|
||||
|
||||
collectgarbage()
|
||||
assert(A == 10) -- number of normal collections
|
||||
collectgarbage("restart")
|
||||
end
|
||||
|
||||
@@ -353,40 +353,36 @@ GC()
|
||||
|
||||
|
||||
-- testing errors during GC
|
||||
do
|
||||
collectgarbage("stop") -- stop collection
|
||||
local u = {}
|
||||
local s = {}; setmetatable(s, {__mode = 'k'})
|
||||
setmetatable(u, {__gc = function (o)
|
||||
local i = s[o]
|
||||
s[i] = true
|
||||
assert(not s[i - 1]) -- check proper finalization order
|
||||
if i == 8 then error("here") end -- error during GC
|
||||
end})
|
||||
if T then
|
||||
collectgarbage("stop") -- stop collection
|
||||
local u = {}
|
||||
local s = {}; setmetatable(s, {__mode = 'k'})
|
||||
setmetatable(u, {__gc = function (o)
|
||||
local i = s[o]
|
||||
s[i] = true
|
||||
assert(not s[i - 1]) -- check proper finalization order
|
||||
if i == 8 then error("@expected@") end -- error during GC
|
||||
end})
|
||||
|
||||
for i = 6, 10 do
|
||||
local n = setmetatable({}, getmetatable(u))
|
||||
s[n] = i
|
||||
end
|
||||
for i = 6, 10 do
|
||||
local n = setmetatable({}, getmetatable(u))
|
||||
s[n] = i
|
||||
end
|
||||
|
||||
assert(not pcall(collectgarbage))
|
||||
for i = 8, 10 do assert(s[i]) end
|
||||
collectgarbage()
|
||||
assert(string.find(_WARN, "error in __gc metamethod"))
|
||||
assert(string.match(_WARN, "@(.-)@") == "expected")
|
||||
for i = 8, 10 do assert(s[i]) end
|
||||
|
||||
for i = 1, 5 do
|
||||
local n = setmetatable({}, getmetatable(u))
|
||||
s[n] = i
|
||||
end
|
||||
for i = 1, 5 do
|
||||
local n = setmetatable({}, getmetatable(u))
|
||||
s[n] = i
|
||||
end
|
||||
|
||||
collectgarbage()
|
||||
for i = 1, 10 do assert(s[i]) end
|
||||
collectgarbage()
|
||||
for i = 1, 10 do assert(s[i]) end
|
||||
|
||||
getmetatable(u).__gc = false
|
||||
|
||||
|
||||
-- __gc errors with non-string messages
|
||||
setmetatable({}, {__gc = function () error{} end})
|
||||
local a, b = pcall(collectgarbage)
|
||||
assert(not a and type(b) == "string" and string.find(b, "error in __gc"))
|
||||
getmetatable(u).__gc = false
|
||||
|
||||
end
|
||||
print '+'
|
||||
@@ -478,9 +474,11 @@ end
|
||||
|
||||
|
||||
-- errors during collection
|
||||
u = setmetatable({}, {__gc = function () error "!!!" end})
|
||||
u = nil
|
||||
assert(not pcall(collectgarbage))
|
||||
if T then
|
||||
u = setmetatable({}, {__gc = function () error "@expected error" end})
|
||||
u = nil
|
||||
collectgarbage()
|
||||
end
|
||||
|
||||
|
||||
if not _soft then
|
||||
@@ -645,11 +643,26 @@ do
|
||||
end
|
||||
|
||||
-- create several objects to raise errors when collected while closing state
|
||||
do
|
||||
local mt = {__gc = function (o) return o + 1 end}
|
||||
for i = 1,10 do
|
||||
if T then
|
||||
local error, assert, warn, find = error, assert, warn, string.find
|
||||
local n = 0
|
||||
local lastmsg
|
||||
local mt = {__gc = function (o)
|
||||
n = n + 1
|
||||
assert(n == o[1])
|
||||
if n == 1 then
|
||||
_WARN = nil
|
||||
elseif n == 2 then
|
||||
assert(find(_WARN, "@expected warning"))
|
||||
lastmsg = _WARN -- get message from previous error (first 'o')
|
||||
else
|
||||
assert(lastmsg == _WARN) -- subsequent error messages are equal
|
||||
end
|
||||
error"@expected warning"
|
||||
end}
|
||||
for i = 10, 1, -1 do
|
||||
-- create object and preserve it until the end
|
||||
table.insert(___Glob, setmetatable({}, mt))
|
||||
table.insert(___Glob, setmetatable({i}, mt))
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
Reference in New Issue
Block a user