From f645d3157372c73573dff221c5b26691cb0e7d56 Mon Sep 17 00:00:00 2001 From: Roberto Ierusalimschy Date: Wed, 31 Jul 2019 10:43:51 -0300 Subject: To-be-closed variables must be closed on initialization When initializing a to-be-closed variable, check whether it has a '__close' metamethod (or is a false value) and raise an error if if it hasn't. This produces more accurate error messages. (The check before closing still need to be done: in the C API, the value is not constant; and the object may lose its '__close' metamethod during the block.) --- testes/api.lua | 11 ++++++++++- testes/locals.lua | 23 ++++++++++++----------- 2 files changed, 22 insertions(+), 12 deletions(-) (limited to 'testes') diff --git a/testes/api.lua b/testes/api.lua index 3f7f7596..f6915c3e 100644 --- a/testes/api.lua +++ b/testes/api.lua @@ -1096,7 +1096,7 @@ do assert(type(a[1]) == "string" and a[2][1] == 11) assert(#openresource == 0) -- was closed - -- error + -- closing by error local a, b = pcall(T.makeCfunc[[ call 0 1 # create resource toclose -1 # mark it to be closed @@ -1105,6 +1105,15 @@ do assert(a == false and b[1] == 11) assert(#openresource == 0) -- was closed + -- non-closable value + local a, b = pcall(T.makeCfunc[[ + newtable # create non-closable object + toclose -1 # mark it to be closed (shoud raise an error) + abort # will not be executed + ]]) + assert(a == false and + string.find(b, "non%-closable value")) + local function check (n) assert(#openresource == n) end diff --git a/testes/locals.lua b/testes/locals.lua index 3b145ca3..6eb1ba0e 100644 --- a/testes/locals.lua +++ b/testes/locals.lua @@ -215,11 +215,13 @@ end do local a = {} do + local b = false -- not to be closed local x = setmetatable({"x"}, {__close = function (self) a[#a + 1] = self[1] end}) local w, y , z = func2close(function (self, err) assert(err == nil); a[#a + 1] = "y" end, 10, 20) + local c = nil -- not to be closed a[#a + 1] = "in" assert(w == 10 and z == 20) end @@ -325,24 +327,22 @@ do -- errors in __close end -do - - -- errors due to non-closable values +do -- errors due to non-closable values local function foo () local x = {} + os.exit(false) -- should not run end local stat, msg = pcall(foo) - assert(not stat and string.find(msg, "variable 'x'")) + assert(not stat and + string.find(msg, "variable 'x' got a non%-closable value")) - - -- with other errors, non-closable values are ignored local function foo () - local x = 34 - local y = func2close(function () error(32) end) + local xyz = setmetatable({}, {__close = print}) + getmetatable(xyz).__close = nil -- remove metamethod end local stat, msg = pcall(foo) - assert(not stat and msg == 32) - + assert(not stat and + string.find(msg, "attempt to close non%-closable variable 'xyz'")) end @@ -519,7 +519,8 @@ end -- a suspended coroutine should not close its variables when collected local co co = coroutine.wrap(function() - local x = function () os.exit(false) end -- should not run + -- should not run + local x = func2close(function () os.exit(false) end) co = nil coroutine.yield() end) -- cgit v1.2.3-55-g6feb