From b4d5dff8ec4f1c8a44db66d368e95d359b04aea7 Mon Sep 17 00:00:00 2001 From: Roberto Ierusalimschy Date: Wed, 5 Jun 2019 13:16:25 -0300 Subject: Multiple errors in '__toclose' report the first one When there are multiple errors when closing objects, the error reported by the protected call is the first one, for two reasons: First, other errors may be caused by this one; second, the first error is handled in the original execution context, and therefore has the full traceback. --- testes/coroutine.lua | 10 +++++++++- testes/locals.lua | 37 ++++++++++++++++++++++++------------- 2 files changed, 33 insertions(+), 14 deletions(-) (limited to 'testes') diff --git a/testes/coroutine.lua b/testes/coroutine.lua index 198a5870..f2c0da8b 100644 --- a/testes/coroutine.lua +++ b/testes/coroutine.lua @@ -163,15 +163,23 @@ do assert(not X and coroutine.status(co) == "dead") -- error closing a coroutine + local x = 0 co = coroutine.create(function() + local y = func2close(function (self,err) + if (err ~= 111) then os.exit(false) end -- should not happen + x = 200 + error(200) + end) local x = func2close(function (self, err) assert(err == nil); error(111) end) coroutine.yield() end) coroutine.resume(co) + assert(x == 0) local st, msg = coroutine.close(co) - assert(not st and coroutine.status(co) == "dead" and msg == 111) + assert(st == false and coroutine.status(co) == "dead" and msg == 111) + assert(x == 200) end diff --git a/testes/locals.lua b/testes/locals.lua index 7834d7da..dccda28f 100644 --- a/testes/locals.lua +++ b/testes/locals.lua @@ -267,14 +267,14 @@ do -- errors in __close if err then error(4) end end local stat, msg = pcall(foo, false) - assert(msg == 1) - assert(log[1] == 10 and log[2] == 3 and log[3] == 2 and log[4] == 2 + assert(msg == 3) + assert(log[1] == 10 and log[2] == 3 and log[3] == 3 and log[4] == 3 and #log == 4) log = {} local stat, msg = pcall(foo, true) - assert(msg == 1) - assert(log[1] == 4 and log[2] == 3 and log[3] == 2 and log[4] == 2 + assert(msg == 4) + assert(log[1] == 4 and log[2] == 4 and log[3] == 4 and log[4] == 4 and #log == 4) -- error in toclose in vararg function @@ -317,7 +317,7 @@ if rawget(_G, "T") then local x = setmetatable({}, {__close = function () T.alloccount(0); local x = {} -- force a memory error end}) - error("a") -- common error inside the function's body + error(1000) -- common error inside the function's body end stack(5) -- ensure a minimal number of CI structures @@ -325,7 +325,7 @@ if rawget(_G, "T") then -- despite memory error, 'y' will be executed and -- memory limit will be lifted local _, msg = pcall(foo) - assert(msg == "not enough memory") + assert(msg == 1000) local close = func2close(function (self, msg) T.alloccount() @@ -368,8 +368,7 @@ if rawget(_G, "T") then end local _, msg = pcall(test) - assert(msg == 1000) - + assert(msg == "not enough memory") -- reported error is the first one do -- testing 'toclose' in C string buffer collectgarbage() @@ -453,15 +452,27 @@ end do -- error in a wrapped coroutine raising errors when closing a variable - local x = false + local x = 0 local co = coroutine.wrap(function () - local xv = func2close(function () error("XXX") end) + local xx = func2close(function () x = x + 1; error("YYY") end) + local xv = func2close(function () x = x + 1; error("XXX") end) coroutine.yield(100) error(200) end) - assert(co() == 100) - local st, msg = pcall(co) - -- should get last error raised + assert(co() == 100); assert(x == 0) + local st, msg = pcall(co); assert(x == 2) + assert(not st and msg == 200) -- should get first error raised + + x = 0 + co = coroutine.wrap(function () + local xx = func2close(function () x = x + 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) + -- should get first error raised assert(not st and string.find(msg, "%w+%.%w+:%d+: XXX")) end -- cgit v1.2.3-55-g6feb