mirror of
https://github.com/lua/lua
synced 2024-11-22 04:41:23 +03:00
Bug: stack overflow with nesting of coroutine.close
This commit is contained in:
parent
b85816b9a8
commit
1e64c1391f
@ -76,7 +76,7 @@ static int luaB_auxwrap (lua_State *L) {
|
||||
if (l_unlikely(r < 0)) { /* error? */
|
||||
int stat = lua_status(co);
|
||||
if (stat != LUA_OK && stat != LUA_YIELD) { /* error in the coroutine? */
|
||||
stat = lua_resetthread(co); /* close its tbc variables */
|
||||
stat = lua_resetthread(co, L); /* close its tbc variables */
|
||||
lua_assert(stat != LUA_OK);
|
||||
lua_xmove(co, L, 1); /* move error message to the caller */
|
||||
}
|
||||
@ -172,7 +172,7 @@ static int luaB_close (lua_State *L) {
|
||||
int status = auxstatus(L, co);
|
||||
switch (status) {
|
||||
case COS_DEAD: case COS_YIELD: {
|
||||
status = lua_resetthread(co);
|
||||
status = lua_resetthread(co, L);
|
||||
if (status == LUA_OK) {
|
||||
lua_pushboolean(L, 1);
|
||||
return 1;
|
||||
|
3
lstate.c
3
lstate.c
@ -343,9 +343,10 @@ int luaE_resetthread (lua_State *L, int status) {
|
||||
}
|
||||
|
||||
|
||||
LUA_API int lua_resetthread (lua_State *L) {
|
||||
LUA_API int lua_resetthread (lua_State *L, lua_State *from) {
|
||||
int status;
|
||||
lua_lock(L);
|
||||
L->nCcalls = (from) ? getCcalls(from) : 0;
|
||||
status = luaE_resetthread(L, L->status);
|
||||
lua_unlock(L);
|
||||
return status;
|
||||
|
2
ltests.c
2
ltests.c
@ -1533,7 +1533,7 @@ static int runC (lua_State *L, lua_State *L1, const char *pc) {
|
||||
lua_newthread(L1);
|
||||
}
|
||||
else if EQ("resetthread") {
|
||||
lua_pushinteger(L1, lua_resetthread(L1));
|
||||
lua_pushinteger(L1, lua_resetthread(L1, L));
|
||||
}
|
||||
else if EQ("newuserdata") {
|
||||
lua_newuserdata(L1, getnum);
|
||||
|
2
lua.h
2
lua.h
@ -153,7 +153,7 @@ extern const char lua_ident[];
|
||||
LUA_API lua_State *(lua_newstate) (lua_Alloc f, void *ud);
|
||||
LUA_API void (lua_close) (lua_State *L);
|
||||
LUA_API lua_State *(lua_newthread) (lua_State *L);
|
||||
LUA_API int (lua_resetthread) (lua_State *L);
|
||||
LUA_API int (lua_resetthread) (lua_State *L, lua_State *from);
|
||||
|
||||
LUA_API lua_CFunction (lua_atpanic) (lua_State *L, lua_CFunction panicf);
|
||||
|
||||
|
@ -4160,7 +4160,7 @@ and then pops the top element.
|
||||
|
||||
}
|
||||
|
||||
@APIEntry{int lua_resetthread (lua_State *L);|
|
||||
@APIEntry{int lua_resetthread (lua_State *L, lua_State *from);|
|
||||
@apii{0,?,-}
|
||||
|
||||
Resets a thread, cleaning its call stack and closing all pending
|
||||
@ -4173,6 +4173,11 @@ or an error status otherwise.
|
||||
In case of error,
|
||||
leaves the error object on the top of the stack.
|
||||
|
||||
The parameter @id{from} represents the coroutine that is resetting @id{L}.
|
||||
If there is no such coroutine,
|
||||
this parameter can be @id{NULL}.
|
||||
(This parameter was introduced in @N{release 5.4.5}.)
|
||||
|
||||
}
|
||||
|
||||
@APIEntry{int lua_resume (lua_State *L, lua_State *from, int nargs,
|
||||
|
@ -84,6 +84,32 @@ do -- bug in 5.4.0
|
||||
end
|
||||
|
||||
|
||||
do -- bug since 5.4.0
|
||||
local count = 0
|
||||
print("chain of 'coroutine.close'")
|
||||
-- create N coroutines forming a list so that each one, when closed,
|
||||
-- closes the previous one. (With a large enough N, previous Lua
|
||||
-- versions crash in this test.)
|
||||
local coro = false
|
||||
for i = 1, 1000 do
|
||||
local previous = coro
|
||||
coro = coroutine.create(function()
|
||||
local cc <close> = setmetatable({}, {__close=function()
|
||||
count = count + 1
|
||||
if previous then
|
||||
assert(coroutine.close(previous))
|
||||
end
|
||||
end})
|
||||
coroutine.yield() -- leaves 'cc' pending to be closed
|
||||
end)
|
||||
assert(coroutine.resume(coro)) -- start it and run until it yields
|
||||
end
|
||||
local st, msg = coroutine.close(coro)
|
||||
assert(not st and string.find(msg, "C stack overflow"))
|
||||
print("final count: ", count)
|
||||
end
|
||||
|
||||
|
||||
do
|
||||
print("nesting of resuming yielded coroutines")
|
||||
local count = 0
|
||||
|
Loading…
Reference in New Issue
Block a user