浏览代码

resist errors in finalizers during lua_close

Roberto Ierusalimschy 22 年之前
父节点
当前提交
6f207b15fb
共有 3 个文件被更改,包括 18 次插入15 次删除
  1. 5 11
      lgc.c
  2. 3 2
      lgc.h
  3. 10 2
      lstate.c

+ 5 - 11
lgc.c

@@ -1,5 +1,5 @@
 /*
 /*
-** $Id: lgc.c,v 1.166 2002/12/04 17:38:31 roberto Exp roberto $
+** $Id: lgc.c,v 1.167 2002/12/19 11:11:55 roberto Exp roberto $
 ** Garbage Collector
 ** Garbage Collector
 ** See Copyright Notice in lua.h
 ** See Copyright Notice in lua.h
 */
 */
@@ -110,7 +110,7 @@ static void marktmu (GCState *st) {
 
 
 
 
 /* move `dead' udata that need finalization to list `tmudata' */
 /* move `dead' udata that need finalization to list `tmudata' */
-static void separateudata (lua_State *L) {
+void luaC_separateudata (lua_State *L) {
   GCObject **p = &G(L)->rootudata;
   GCObject **p = &G(L)->rootudata;
   GCObject *curr;
   GCObject *curr;
   GCObject *collected = NULL;  /* to collect udata with gc event */
   GCObject *collected = NULL;  /* to collect udata with gc event */
@@ -411,7 +411,7 @@ static void do1gcTM (lua_State *L, Udata *udata) {
 }
 }
 
 
 
 
-static void callGCTM (lua_State *L) {
+void luaC_callGCTM (lua_State *L) {
   lu_byte oldah = L->allowhook;
   lu_byte oldah = L->allowhook;
   L->allowhook = 0;  /* stop debug hooks during GC tag methods */
   L->allowhook = 0;  /* stop debug hooks during GC tag methods */
   L->top++;  /* reserve space to keep udata while runs its gc method */
   L->top++;  /* reserve space to keep udata while runs its gc method */
@@ -431,12 +431,6 @@ static void callGCTM (lua_State *L) {
 }
 }
 
 
 
 
-void luaC_callallgcTM (lua_State *L) {
-  separateudata(L);
-  callGCTM(L);  /* call their GC tag methods */
-}
-
-
 void luaC_sweep (lua_State *L, int all) {
 void luaC_sweep (lua_State *L, int all) {
   if (all) all = 256;  /* larger than any mark */
   if (all) all = 256;  /* larger than any mark */
   sweeplist(L, &G(L)->rootudata, all);
   sweeplist(L, &G(L)->rootudata, all);
@@ -469,7 +463,7 @@ static void mark (lua_State *L) {
   wkv = st.wkv;  /* keys must be cleared after preserving udata */
   wkv = st.wkv;  /* keys must be cleared after preserving udata */
   st.wkv = NULL;
   st.wkv = NULL;
   st.wv = NULL;
   st.wv = NULL;
-  separateudata(L);  /* separate userdata to be preserved */
+  luaC_separateudata(L);  /* separate userdata to be preserved */
   marktmu(&st);  /* mark `preserved' userdata */
   marktmu(&st);  /* mark `preserved' userdata */
   propagatemarks(&st);  /* remark, to propagate `preserveness' */
   propagatemarks(&st);  /* remark, to propagate `preserveness' */
   cleartablekeys(wkv);
   cleartablekeys(wkv);
@@ -485,7 +479,7 @@ void luaC_collectgarbage (lua_State *L) {
   mark(L);
   mark(L);
   luaC_sweep(L, 0);
   luaC_sweep(L, 0);
   checkSizes(L);
   checkSizes(L);
-  callGCTM(L);
+  luaC_callGCTM(L);
 }
 }
 
 
 
 

+ 3 - 2
lgc.h

@@ -1,5 +1,5 @@
 /*
 /*
-** $Id: lgc.h,v 1.16 2002/08/30 19:09:21 roberto Exp roberto $
+** $Id: lgc.h,v 1.17 2002/11/25 12:38:47 roberto Exp roberto $
 ** Garbage Collector
 ** Garbage Collector
 ** See Copyright Notice in lua.h
 ** See Copyright Notice in lua.h
 */
 */
@@ -15,7 +15,8 @@
 			  luaC_collectgarbage(L)
 			  luaC_collectgarbage(L)
 
 
 
 
-void luaC_callallgcTM (lua_State *L);
+void luaC_separateudata (lua_State *L);
+void luaC_callGCTM (lua_State *L);
 void luaC_sweep (lua_State *L, int all);
 void luaC_sweep (lua_State *L, int all);
 void luaC_collectgarbage (lua_State *L);
 void luaC_collectgarbage (lua_State *L);
 void luaC_link (lua_State *L, GCObject *o, lu_byte tt);
 void luaC_link (lua_State *L, GCObject *o, lu_byte tt);

+ 10 - 2
lstate.c

@@ -1,5 +1,5 @@
 /*
 /*
-** $Id: lstate.c,v 1.117 2002/12/04 17:38:31 roberto Exp roberto $
+** $Id: lstate.c,v 1.118 2002/12/19 13:21:08 roberto Exp roberto $
 ** Global State
 ** Global State
 ** See Copyright Notice in lua.h
 ** See Copyright Notice in lua.h
 */
 */
@@ -197,10 +197,18 @@ LUA_API lua_State *lua_open (void) {
 }
 }
 
 
 
 
+static void callallgcTM (lua_State *L, void *ud) {
+  UNUSED(ud);
+  luaC_callGCTM(L);  /* call GC metamethods for all udata */
+}
+
+
 LUA_API void lua_close (lua_State *L) {
 LUA_API void lua_close (lua_State *L) {
   lua_lock(L);
   lua_lock(L);
   L = G(L)->mainthread;  /* only the main thread can be closed */
   L = G(L)->mainthread;  /* only the main thread can be closed */
-  luaC_callallgcTM(L);  /* call GC tag methods for all udata */
+  luaC_separateudata(L);  /* separate udata that have GC metamethods */
+  /* repeat until no more errors */
+  while (luaD_rawrunprotected(L, callallgcTM, NULL) != 0) /* skip */;
   lua_assert(G(L)->tmudata == NULL);
   lua_assert(G(L)->tmudata == NULL);
   close_state(L);
   close_state(L);
 }
 }