diff --git a/regress/145-assertion-on-dead.lua b/regress/145-assertion-on-dead.lua new file mode 100755 index 0000000..49d71d3 --- /dev/null +++ b/regress/145-assertion-on-dead.lua @@ -0,0 +1,20 @@ +#!/bin/sh +_=[[ + . "${0%%/*}/regress.sh" + exec runlua "$0" "$@" +]] +require"regress".export".*" + +local co = coroutine.create(function() + coroutine.yield() +end) +coroutine.resume(co) -- kick off coroutine +coroutine.resume(co) -- resume a yield with no arguments +-- co is now dead + +local cq = require"cqueues".new() +cq:attach(co) +check(cq:step()) + +say"OK" + diff --git a/src/cqueues.c b/src/cqueues.c index 807275f..547da97 100644 --- a/src/cqueues.c +++ b/src/cqueues.c @@ -1982,10 +1982,22 @@ static cqs_status_t cqueue_resume(lua_State *L, struct cqueue *Q, struct callinf } } else { nargs = lua_gettop(T->L); - if (status != LUA_YIELD) { + if (status == LUA_OK && lua_getstack(T->L, 0, &(lua_Debug){}) != 0) { + /* already running */ + lua_pushliteral(L, "cannot resume non-suspended coroutine"); + I->error.value = lua_gettop(L); + err_setthread(L, I, T); + goto defunct; + } else if ((status != LUA_OK && status != LUA_YIELD) || nargs == 0) { + /* dead coroutine */ + lua_pushliteral(L, "cannot resume dead coroutine"); + I->error.value = lua_gettop(L); + err_setthread(L, I, T); + goto defunct; + } else if (status == LUA_OK) { + /* initial */ nargs -= 1; - assert(nargs >= 0); - } + } /* else normal yield */ } timer_del(Q, &T->timer); @@ -2294,9 +2306,8 @@ static int cqueue_wrap(lua_State *L) { luaL_checktype(L, 2, LUA_TFUNCTION); newL = lua_newthread(L); - for (i = 2; i <= top; i++) { - lua_pushvalue(L, i); - } + lua_insert(L, 2); + luaL_checkstack(newL, top - 1, "too many arguments"); lua_xmove(L, newL, top - 1); thread_add(L, Q, &I, -1);