From c6f7181e910b6b2ff1346b5486a31be87b1da5af Mon Sep 17 00:00:00 2001 From: Roberto Ierusalimschy Date: Tue, 1 Jan 2019 12:14:56 -0200 Subject: No more LUA_ERRGCMM errors Errors in finalizers (__gc metamethods) are never propagated. Instead, they generate a warning. --- testes/all.lua | 11 ++++---- testes/api.lua | 28 ++++++------------- testes/gc.lua | 87 +++++++++++++++++++++++++++++++++------------------------- 3 files changed, 65 insertions(+), 61 deletions(-) (limited to 'testes') diff --git a/testes/all.lua b/testes/all.lua index bde4195e..506afad2 100644 --- a/testes/all.lua +++ b/testes/all.lua @@ -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) diff --git a/testes/api.lua b/testes/api.lua index b4d63866..893a36cb 100644 --- a/testes/api.lua +++ b/testes/api.lua @@ -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 diff --git a/testes/gc.lua b/testes/gc.lua index 8b9179c8..84e8ffb7 100644 --- a/testes/gc.lua +++ b/testes/gc.lua @@ -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}) - -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 - -for i = 1, 5 do - local n = setmetatable({}, getmetatable(u)) - s[n] = i -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 -collectgarbage() -for i = 1, 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 -getmetatable(u).__gc = false + for i = 1, 5 do + local n = setmetatable({}, getmetatable(u)) + s[n] = i + end + collectgarbage() + for i = 1, 10 do assert(s[i]) end --- __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 -- cgit v1.2.3-55-g6feb