diff options
author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2020-12-30 11:20:22 -0300 |
---|---|---|
committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2020-12-30 11:20:22 -0300 |
commit | ce101dcaf73ff6d610593230d41b63c163a91519 (patch) | |
tree | 6417f02cb96257a835fa908bfea15c2557a41413 /testes/coroutine.lua | |
parent | 553b37ce4ff758d8cf80d48a21287526c92221c6 (diff) | |
download | lua-github-ce101dcaf73ff6d610593230d41b63c163a91519.tar.gz |
Handles '__close' errors in coroutines in "coroutine style"
Errors in '__close' metamethods in coroutines are handled by the same
logic that handles other errors, through 'recover'.
Diffstat (limited to 'testes/coroutine.lua')
-rw-r--r-- | testes/coroutine.lua | 41 |
1 files changed, 39 insertions, 2 deletions
diff --git a/testes/coroutine.lua b/testes/coroutine.lua index 0a970e98..fbeabd07 100644 --- a/testes/coroutine.lua +++ b/testes/coroutine.lua @@ -123,7 +123,7 @@ assert(#a == 22 and a[#a] == 79) x, a = nil --- coroutine closing +print("to-be-closed variables in coroutines") local function func2close (f) return setmetatable({}, {__close = f}) @@ -189,7 +189,6 @@ do local st, msg = coroutine.close(co) assert(st == false and coroutine.status(co) == "dead" and msg == 200) assert(x == 200) - end do @@ -207,6 +206,44 @@ do local st1, st2, err = coroutine.resume(co) assert(st1 and not st2 and err == 43) assert(X == 43 and Y.name == "pcall") + + -- recovering from errors in __close metamethods + local track = {} + + local function h (o) + local hv <close> = o + return 1 + end + + local function foo () + local x <close> = func2close(function(_,msg) + track[#track + 1] = msg or false + error(20) + end) + local y <close> = func2close(function(_,msg) + track[#track + 1] = msg or false + return 1000 + end) + local z <close> = func2close(function(_,msg) + track[#track + 1] = msg or false + error(10) + end) + coroutine.yield(1) + h(func2close(function(_,msg) + track[#track + 1] = msg or false + error(2) + end)) + end + + local co = coroutine.create(pcall) + + local st, res = coroutine.resume(co, foo) -- call 'foo' protected + assert(st and res == 1) -- yield 1 + local st, res1, res2 = coroutine.resume(co) -- continue + assert(coroutine.status(co) == "dead") + assert(st and not res1 and res2 == 20) -- last error (20) + assert(track[1] == false and track[2] == 2 and track[3] == 10 and + track[4] == 10) end |