From 8d6c5fe6d182b399015cdaa6c2c6e669d3727da1 Mon Sep 17 00:00:00 2001 From: daurnimator Date: Wed, 7 Sep 2016 00:29:21 +1000 Subject: [PATCH 1/3] cqueues:wrap: Remember to checkstack - Instead of re-pushing all arguments, just use lua_insert to get thread below args - Need to check the new stack to ensure we have enough slots --- src/cqueues.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/cqueues.c b/src/cqueues.c index 807275f..2288569 100644 --- a/src/cqueues.c +++ b/src/cqueues.c @@ -2294,9 +2294,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); From b8041a68bf24ea9e1f1d39c6c6c5448ac8cc1264 Mon Sep 17 00:00:00 2001 From: daurnimator Date: Wed, 7 Sep 2016 01:04:07 +1000 Subject: [PATCH 2/3] src/cqueues: Detect if trying to resume a running or dead coroutine --- regress/145-assertion-on-dead.lua | 20 ++++++++++++++++++++ src/cqueues.c | 18 +++++++++++++++--- 2 files changed, 35 insertions(+), 3 deletions(-) create mode 100755 regress/145-assertion-on-dead.lua 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 2288569..a7e187c 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); From 80aef124ecf4c56c253762e4da5c38069e251d77 Mon Sep 17 00:00:00 2001 From: daurnimator Date: Fri, 9 Sep 2016 15:16:22 +1000 Subject: [PATCH 3/3] src/cqueues.c: Use != 0 instead of > 0 As requested in https://github.com/wahern/cqueues/pull/145#discussion_r78129250 --- src/cqueues.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cqueues.c b/src/cqueues.c index a7e187c..547da97 100644 --- a/src/cqueues.c +++ b/src/cqueues.c @@ -1982,7 +1982,7 @@ static cqs_status_t cqueue_resume(lua_State *L, struct cqueue *Q, struct callinf } } else { nargs = lua_gettop(T->L); - if (status == LUA_OK && lua_getstack(T->L, 0, &(lua_Debug){}) > 0) { + 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);