From c220b0a5d099372e58e517b9f13eaa7bb0bec45c Mon Sep 17 00:00:00 2001 From: Roberto Ierusalimschy Date: Tue, 16 Jul 2019 15:17:47 -0300 Subject: '__close' method may be called again in case of error An error in a closing method may be caused by a lack of resources, such as memory or stack space, and the error may free enough resources (by unwinding the stack) to allow the method to work if called again. If the closing method is already running after some error (including its own), it is not called again. --- testes/locals.lua | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) (limited to 'testes') diff --git a/testes/locals.lua b/testes/locals.lua index 1b82dd7f..73267d02 100644 --- a/testes/locals.lua +++ b/testes/locals.lua @@ -295,18 +295,23 @@ do -- errors in __close local y = func2close(function (self, msg) log[#log + 1] = msg; error(2) end) local z = - func2close(function (self, msg) log[#log + 1] = msg or 10; error(3) end) + func2close(function (self, msg) + log[#log + 1] = (msg or 10) + 1; + error(3) + end) if err then error(4) end end local stat, msg = pcall(foo, false) assert(msg == 3) - assert(log[1] == 10 and log[2] == 3 and log[3] == 3 and log[4] == 3 - and #log == 4) + -- 'z' close is called twice + assert(log[1] == 11 and log[2] == 4 and log[3] == 3 and log[4] == 3 + and log[5] == 3 and #log == 5) log = {} local stat, msg = pcall(foo, true) assert(msg == 4) - assert(log[1] == 4 and log[2] == 4 and log[3] == 4 and log[4] == 4 + -- 'z' close is called once + assert(log[1] == 5 and log[2] == 4 and log[3] == 4 and log[4] == 4 and #log == 4) -- error in toclose in vararg function @@ -495,15 +500,17 @@ do local st, msg = pcall(co); assert(x == 2) assert(not st and msg == 200) -- should get first error raised - x = 0 + local x = 0 + local y = 0 co = coroutine.wrap(function () - local xx = func2close(function () x = x + 1; error("YYY") end) + local xx = func2close(function () y = y + 1; error("YYY") end) local xv = func2close(function () x = x + 1; error("XXX") end) coroutine.yield(100) return 200 end) assert(co() == 100); assert(x == 0) - local st, msg = pcall(co); assert(x == 2) + local st, msg = pcall(co) + assert(x == 2 and y == 1) -- first close is called twice -- should get first error raised assert(not st and string.find(msg, "%w+%.%w+:%d+: XXX")) end -- cgit v1.2.3-55-g6feb