diff options
author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2019-07-16 15:17:47 -0300 |
---|---|---|
committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2019-07-16 15:17:47 -0300 |
commit | c220b0a5d099372e58e517b9f13eaa7bb0bec45c (patch) | |
tree | 5d5a083a4a7e924f5af052295cef49792305a989 /testes | |
parent | 298f383ffcc30d0799fbca0293175f647fe6bccf (diff) | |
download | lua-c220b0a5d099372e58e517b9f13eaa7bb0bec45c.tar.gz lua-c220b0a5d099372e58e517b9f13eaa7bb0bec45c.tar.bz2 lua-c220b0a5d099372e58e517b9f13eaa7bb0bec45c.zip |
'__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.
Diffstat (limited to 'testes')
-rw-r--r-- | testes/locals.lua | 21 |
1 files changed, 14 insertions, 7 deletions
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 | |||
295 | local <toclose> y = | 295 | local <toclose> y = |
296 | func2close(function (self, msg) log[#log + 1] = msg; error(2) end) | 296 | func2close(function (self, msg) log[#log + 1] = msg; error(2) end) |
297 | local <toclose> z = | 297 | local <toclose> z = |
298 | func2close(function (self, msg) log[#log + 1] = msg or 10; error(3) end) | 298 | func2close(function (self, msg) |
299 | log[#log + 1] = (msg or 10) + 1; | ||
300 | error(3) | ||
301 | end) | ||
299 | if err then error(4) end | 302 | if err then error(4) end |
300 | end | 303 | end |
301 | local stat, msg = pcall(foo, false) | 304 | local stat, msg = pcall(foo, false) |
302 | assert(msg == 3) | 305 | assert(msg == 3) |
303 | assert(log[1] == 10 and log[2] == 3 and log[3] == 3 and log[4] == 3 | 306 | -- 'z' close is called twice |
304 | and #log == 4) | 307 | assert(log[1] == 11 and log[2] == 4 and log[3] == 3 and log[4] == 3 |
308 | and log[5] == 3 and #log == 5) | ||
305 | 309 | ||
306 | log = {} | 310 | log = {} |
307 | local stat, msg = pcall(foo, true) | 311 | local stat, msg = pcall(foo, true) |
308 | assert(msg == 4) | 312 | assert(msg == 4) |
309 | assert(log[1] == 4 and log[2] == 4 and log[3] == 4 and log[4] == 4 | 313 | -- 'z' close is called once |
314 | assert(log[1] == 5 and log[2] == 4 and log[3] == 4 and log[4] == 4 | ||
310 | and #log == 4) | 315 | and #log == 4) |
311 | 316 | ||
312 | -- error in toclose in vararg function | 317 | -- error in toclose in vararg function |
@@ -495,15 +500,17 @@ do | |||
495 | local st, msg = pcall(co); assert(x == 2) | 500 | local st, msg = pcall(co); assert(x == 2) |
496 | assert(not st and msg == 200) -- should get first error raised | 501 | assert(not st and msg == 200) -- should get first error raised |
497 | 502 | ||
498 | x = 0 | 503 | local x = 0 |
504 | local y = 0 | ||
499 | co = coroutine.wrap(function () | 505 | co = coroutine.wrap(function () |
500 | local <toclose> xx = func2close(function () x = x + 1; error("YYY") end) | 506 | local <toclose> xx = func2close(function () y = y + 1; error("YYY") end) |
501 | local <toclose> xv = func2close(function () x = x + 1; error("XXX") end) | 507 | local <toclose> xv = func2close(function () x = x + 1; error("XXX") end) |
502 | coroutine.yield(100) | 508 | coroutine.yield(100) |
503 | return 200 | 509 | return 200 |
504 | end) | 510 | end) |
505 | assert(co() == 100); assert(x == 0) | 511 | assert(co() == 100); assert(x == 0) |
506 | local st, msg = pcall(co); assert(x == 2) | 512 | local st, msg = pcall(co) |
513 | assert(x == 2 and y == 1) -- first close is called twice | ||
507 | -- should get first error raised | 514 | -- should get first error raised |
508 | assert(not st and string.find(msg, "%w+%.%w+:%d+: XXX")) | 515 | assert(not st and string.find(msg, "%w+%.%w+:%d+: XXX")) |
509 | end | 516 | end |