瀏覽代碼

Bug: wrong 'nCcalls' when resuming a coroutine

The counter 'nCcalls' now includes the number of CallInfo structures
pre-allocated (so that these "potential" C calls can be made without
checking 'nCcalls'). So, when copying this value from a thread to
another, in 'lua_resume', it must be corrected to the number of
CallInfo structures in the thread being resumed.
Roberto Ierusalimschy 7 年之前
父節點
當前提交
96f9643f33
共有 2 個文件被更改,包括 24 次插入5 次删除
  1. 6 3
      ldo.c
  2. 18 2
      lstate.h

+ 6 - 3
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;
 }

+ 18 - 2
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;
 };