diff --git a/ldo.c b/ldo.c index fb077211..ebb35c97 100644 --- a/ldo.c +++ b/ldo.c @@ -1,5 +1,5 @@ /* -** $Id: ldo.c,v 2.201 2018/05/22 12:02:36 roberto Exp roberto $ +** $Id: ldo.c $ ** Stack and Call structure of Lua ** See Copyright Notice in lua.h */ @@ -137,6 +137,7 @@ l_noret luaD_throw (lua_State *L, int errcode) { int luaD_rawrunprotected (lua_State *L, Pfunc f, void *ud) { unsigned short oldnCcalls = L->nCcalls - L->nci; struct lua_longjmp lj; + lua_assert(L->nCcalls >= L->nci); lj.status = LUA_OK; lj.previous = L->errorJmp; /* chain new error handler */ L->errorJmp = &lj; @@ -653,7 +654,10 @@ LUA_API int lua_resume (lua_State *L, lua_State *from, int nargs, } else if (L->status != LUA_YIELD) return resume_error(L, "cannot resume dead coroutine", nargs); - L->nCcalls = (from) ? from->nCcalls + 1 : 1; + if (from == NULL) + L->nCcalls = 1; + else /* correct 'nCcalls' for this thread */ + L->nCcalls = from->nCcalls - from->nci + L->nci + 1; if (L->nCcalls >= LUAI_MAXCCALLS) return resume_error(L, "C stack overflow", nargs); luai_userstateresume(L, nargs); @@ -677,7 +681,6 @@ LUA_API int lua_resume (lua_State *L, lua_State *from, int nargs, *nresults = (status == LUA_YIELD) ? L->ci->u2.nyield : cast_int(L->top - (L->ci->func + 1)); L->nny = oldnny; /* restore 'nny' */ - L->nCcalls--; lua_unlock(L); return status; } diff --git a/lstate.h b/lstate.h index 0e173b5b..2a36bd96 100644 --- a/lstate.h +++ b/lstate.h @@ -1,5 +1,5 @@ /* -** $Id: lstate.h,v 2.159 2018/06/15 19:31:22 roberto Exp roberto $ +** $Id: lstate.h $ ** Global State ** See Copyright Notice in lua.h */ @@ -49,6 +49,22 @@ */ +/* + +** About 'nCcalls': each thread in Lua (a lua_State) keeps a count of +** how many "C calls" it has in the C stack, to avoid C-stack overflow. +** This count is very rough approximation; it considers only recursive +** functions inside the interpreter, as non-recursive calls can be +** considered using a fixed (although unknown) amount of stack space. +** +** The proper count also includes the number of CallInfo structures +** allocated by Lua, as a kind of "potential" calls. So, when Lua +** calls a function (and "consumes" one CallInfo), it needs neither to +** increment nor to check 'nCcalls', as its use of C stack is already +** accounted for. + +*/ + struct lua_longjmp; /* defined in ldo.c */ @@ -212,7 +228,7 @@ struct lua_State { int basehookcount; int hookcount; unsigned short nny; /* number of non-yieldable calls in stack */ - unsigned short nCcalls; /* number of nested C calls */ + unsigned short nCcalls; /* number of nested C calls + 'nny' */ l_signalT hookmask; lu_byte allowhook; };