|
@@ -1,5 +1,5 @@
|
|
|
/*
|
|
|
-** $Id: ldo.c,v 2.117 2014/06/09 16:32:18 roberto Exp roberto $
|
|
|
+** $Id: ldo.c,v 2.118 2014/06/10 17:41:38 roberto Exp roberto $
|
|
|
** Stack and Call structure of Lua
|
|
|
** See Copyright Notice in lua.h
|
|
|
*/
|
|
@@ -416,7 +416,7 @@ void luaD_call (lua_State *L, StkId func, int nResults, int allowyield) {
|
|
|
** Completes the execution of an interrupted C function, calling its
|
|
|
** continuation function.
|
|
|
*/
|
|
|
-static void finishCcall (lua_State *L) {
|
|
|
+static void finishCcall (lua_State *L, int status) {
|
|
|
CallInfo *ci = L->ci;
|
|
|
int n;
|
|
|
lua_assert(ci->u.c.k != NULL); /* must have a continuation */
|
|
@@ -428,12 +428,9 @@ static void finishCcall (lua_State *L) {
|
|
|
/* finish 'lua_callk'/'lua_pcall' */
|
|
|
adjustresults(L, ci->nresults);
|
|
|
/* call continuation function */
|
|
|
- if (!(ci->callstatus & CIST_STAT)) /* no call status? */
|
|
|
- ci->u.c.status = LUA_YIELD; /* 'default' status */
|
|
|
- lua_assert(ci->u.c.status != LUA_OK);
|
|
|
- ci->callstatus = (ci->callstatus & ~(CIST_YPCALL | CIST_STAT)) | CIST_YIELDED;
|
|
|
+ ci->callstatus = (ci->callstatus & ~CIST_YPCALL) | CIST_YIELDED;
|
|
|
lua_unlock(L);
|
|
|
- n = (*ci->u.c.k)(L, ci->u.c.status, ci->u.c.ctx);
|
|
|
+ n = (*ci->u.c.k)(L, status, ci->u.c.ctx);
|
|
|
lua_lock(L);
|
|
|
api_checknelems(L, n);
|
|
|
/* finish 'luaD_precall' */
|
|
@@ -444,13 +441,18 @@ static void finishCcall (lua_State *L) {
|
|
|
/*
|
|
|
** Executes "full continuation" (everything in the stack) of a
|
|
|
** previously interrupted coroutine until the stack is empty (or another
|
|
|
-** interruption long-jumps out of the loop)
|
|
|
+** interruption long-jumps out of the loop). If the coroutine is
|
|
|
+** recovering from an error, 'ud' points to the error status, which must
|
|
|
+** be passed to the first (only the first) continuation (otherwise the
|
|
|
+** default status is LUA_YIELD).
|
|
|
*/
|
|
|
static void unroll (lua_State *L, void *ud) {
|
|
|
- UNUSED(ud);
|
|
|
+ int status = (ud) ? *(int *)ud : LUA_YIELD;
|
|
|
while (L->ci != &L->base_ci) { /* something in the stack */
|
|
|
- if (!isLua(L->ci)) /* C function? */
|
|
|
- finishCcall(L); /* complete its execution */
|
|
|
+ if (!isLua(L->ci)) { /* C function? */
|
|
|
+ finishCcall(L, status); /* complete its execution */
|
|
|
+ status = LUA_YIELD; /* back to default status */
|
|
|
+ }
|
|
|
else { /* Lua function */
|
|
|
luaV_finishOp(L); /* finish interrupted instruction */
|
|
|
luaV_execute(L); /* execute down to higher C 'boundary' */
|
|
@@ -487,12 +489,10 @@ static int recover (lua_State *L, int status) {
|
|
|
luaF_close(L, oldtop);
|
|
|
seterrorobj(L, status, oldtop);
|
|
|
L->ci = ci;
|
|
|
- L->allowhook = ci->u.c.old_allowhook;
|
|
|
+ L->allowhook = (ci->callstatus & CIST_OAH);
|
|
|
L->nny = 0; /* should be zero to be yieldable */
|
|
|
luaD_shrinkstack(L);
|
|
|
L->errfunc = ci->u.c.old_errfunc;
|
|
|
- ci->callstatus |= CIST_STAT; /* call has error status */
|
|
|
- ci->u.c.status = status; /* (here it is) */
|
|
|
return 1; /* continue running the coroutine */
|
|
|
}
|
|
|
|
|
@@ -536,10 +536,9 @@ static void resume (lua_State *L, void *ud) {
|
|
|
else { /* 'common' yield */
|
|
|
if (ci->u.c.k != NULL) { /* does it have a continuation? */
|
|
|
int n;
|
|
|
- ci->u.c.status = LUA_YIELD; /* 'default' status */
|
|
|
ci->callstatus |= CIST_YIELDED;
|
|
|
lua_unlock(L);
|
|
|
- n = (*ci->u.c.k)(L, ci->u.c.status, ci->u.c.ctx); /* call continuation */
|
|
|
+ n = (*ci->u.c.k)(L, LUA_YIELD, ci->u.c.ctx); /* call continuation */
|
|
|
lua_lock(L);
|
|
|
api_checknelems(L, n);
|
|
|
firstArg = L->top - n; /* yield results come from continuation */
|
|
@@ -563,15 +562,17 @@ LUA_API int lua_resume (lua_State *L, lua_State *from, int nargs) {
|
|
|
status = luaD_rawrunprotected(L, resume, L->top - nargs);
|
|
|
if (status == -1) /* error calling 'lua_resume'? */
|
|
|
status = LUA_ERRRUN;
|
|
|
- else { /* yield or regular error */
|
|
|
+ else { /* yield or error running coroutine */
|
|
|
while (status != LUA_OK && status != LUA_YIELD) { /* error? */
|
|
|
- if (recover(L, status)) /* recover point? */
|
|
|
- status = luaD_rawrunprotected(L, unroll, NULL); /* run continuation */
|
|
|
+ if (recover(L, status)) { /* recover point? */
|
|
|
+ /* unroll continuation */
|
|
|
+ status = luaD_rawrunprotected(L, unroll, &status);
|
|
|
+ }
|
|
|
else { /* unrecoverable error */
|
|
|
L->status = cast_byte(status); /* mark thread as `dead' */
|
|
|
seterrorobj(L, status, L->top);
|
|
|
L->ci->top = L->top;
|
|
|
- break;
|
|
|
+ break; /* stop running it */
|
|
|
}
|
|
|
}
|
|
|
lua_assert(status == L->status);
|