From bfbff3703edae789fa5efa9bf174f8e7cff4ded8 Mon Sep 17 00:00:00 2001 From: Roberto Ierusalimschy Date: Mon, 8 Nov 2021 11:55:25 -0300 Subject: Bug: Wrong status in coroutine during reset When closing variables during 'coroutine.close' or 'lua_resetthread', the status of a coroutine must be set to LUA_OK; a coroutine should not run with any other status. (See assertion in 'lua_callk'.) After the reset, the status should be kept as normal, as any error was already reported. --- testes/coroutine.lua | 44 +++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 43 insertions(+), 1 deletion(-) (limited to 'testes') diff --git a/testes/coroutine.lua b/testes/coroutine.lua index 461e0377..76c9d6e6 100644 --- a/testes/coroutine.lua +++ b/testes/coroutine.lua @@ -136,6 +136,10 @@ do assert(coroutine.status(co) == "dead") local st, msg = coroutine.close(co) assert(st and msg == nil) + -- also ok to close it again + st, msg = coroutine.close(co) + assert(st and msg == nil) + -- cannot close the running coroutine local st, msg = pcall(coroutine.close, coroutine.running()) @@ -149,6 +153,22 @@ do assert(not st and string.find(msg, "normal")) end))() + -- cannot close a coroutine while closing it + do + local co + co = coroutine.create( + function() + local x = func2close(function() + coroutine.close(co) -- try to close it again + end) + coroutine.yield(20) + end) + local st, msg = coroutine.resume(co) + assert(st and msg == 20) + st, msg = coroutine.close(co) + assert(not st and string.find(msg, "running coroutine")) + end + -- to-be-closed variables in coroutines local X @@ -158,6 +178,9 @@ do assert(not st and msg == 100) st, msg = coroutine.close(co) assert(not st and msg == 100) + -- after closing, no more errors + st, msg = coroutine.close(co) + assert(st and msg == nil) co = coroutine.create(function () local x = func2close(function (self, err) @@ -189,6 +212,9 @@ do local st, msg = coroutine.close(co) assert(st == false and coroutine.status(co) == "dead" and msg == 200) assert(x == 200) + -- after closing, no more errors + st, msg = coroutine.close(co) + assert(st and msg == nil) end do @@ -419,7 +445,7 @@ do local X = false A = coroutine.wrap(function() - local _ = setmetatable({}, {__close = function () X = true end}) + local _ = func2close(function () X = true end) return pcall(A, 1) end) st, res = A() @@ -427,6 +453,22 @@ do end +-- bug in 5.4.1 +do + -- coroutine ran close metamethods with invalid status during a + -- reset. + local co + co = coroutine.wrap(function() + local x = func2close(function() return pcall(co) end) + error(111) + end) + local st, errobj = pcall(co) + assert(not st and errobj == 111) + st, errobj = pcall(co) + assert(not st and string.find(errobj, "dead coroutine")) +end + + -- attempt to resume 'normal' coroutine local co1, co2 co1 = coroutine.create(function () return co2() end) -- cgit v1.2.3-55-g6feb