lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


Hello.

Sometimes when calling collectgarbage() inside a coroutine, my application crashes with 'C Stack Overflow'. I managed to track it down to a negative number being assigned to nCcalls in lstate.c and ldo.c, so nCcalls becomes ~65534.

The temporary patch I use to fix this problem:

diff --git a/src/ldo.c b/src/ldo.c
index f2f9062..969a088 100644
--- a/src/ldo.c
+++ b/src/ldo.c
@@ -135,7 +135,8 @@ 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;
+  unsigned short oldnCcalls = L->nCcalls;
+  unsigned short oldnci = L->nci;
   struct lua_longjmp lj;
   lj.status = LUA_OK;
   lj.previous = L->errorJmp;  /* chain new error handler */
@@ -144,7 +145,9 @@ int luaD_rawrunprotected (lua_State *L, Pfunc f, void *ud) {
     (*f)(L, ud);
   );
   L->errorJmp = lj.previous;  /* restore old error handler */
-  L->nCcalls = oldnCcalls + L->nci;
+  L->nCcalls = oldnCcalls;
+  if (L->nCcalls - (oldnci - L->nci) >= 0)
+    L->nCcalls -= oldnci - L->nci;
   return lj.status;
 }
 
diff --git a/src/lstate.c b/src/lstate.c
index a2cc4d9..3342635 100644
--- a/src/lstate.c
+++ b/src/lstate.c
@@ -135,13 +135,13 @@ void luaE_freeCI (lua_State *L) {
   CallInfo *ci = L->ci;
   CallInfo *next = ci->next;
   ci->next = NULL;
-  L->nCcalls -= L->nci;  /* to subtract removed elements from 'nCcalls' */
   while ((ci = next) != NULL) {
     next = ci->next;
     luaM_free(L, ci);
     L->nci--;
+    if (L->nCcalls > 0)
+      L->nCcalls--;  /* to subtract removed elements from 'nCcalls' */
   }
-  L->nCcalls += L->nci;  /* to subtract removed elements from 'nCcalls' */
 }
 
 
@@ -151,16 +150,16 @@ void luaE_freeCI (lua_State *L) {
 void luaE_shrinkCI (lua_State *L) {
   CallInfo *ci = L->ci;
   CallInfo *next2;  /* next's next */
-  L->nCcalls -= L->nci;  /* to subtract removed elements from 'nCcalls' */
   /* while there are two nexts */
   while (ci->next != NULL && (next2 = ci->next->next) != NULL) {
     luaM_free(L, ci->next);  /* free next */
     L->nci--;
+    if (L->nCcalls > 0)
+      L->nCcalls--;  /* to subtract removed elements from 'nCcalls' */
     ci->next = next2;  /* remove 'next' from the list */
     next2->previous = ci;
     ci = next2;  /* keep next's next */
   }
-  L->nCcalls += L->nci;  /* to subtract removed elements from 'nCcalls' */
 }