lua-users home
lua-l archive

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


Roberto Ierusalimschy wrote:
Even if you promise not to touch other Lua objects, Lua itself needs
the metatable of the userdata in order to call its finalizer. If the
metatable is collected (because the last reference to it came from
the userdata and it was not marked in the atomic phase), you are in
trouble...

I'm holding references to all the metatables on the C side, so I should be safe from that at least. If there are no other possible issues, it might work....

I'll try it. I really need to get rid of those stalls.

It seems to work, knock on wood. Here is my patch if someone is interested (line numbers may be off, because there are some other patches in there already):

Index: lua/src/lgc.c
===================================================================
--- lua/src/lgc.c	(revision 4140)
+++ lua/src/lgc.c	(working copy)
@@ -392,6 +392,25 @@
       break;
     }
     case LUA_TUSERDATA: {
+	  #ifdef LUA_SIMPLE_FINALIZERS
+		  global_State *g = G(L);
+		  Udata *udata = rawgco2u(o);
+		  const TValue *tm;
+		  tm = fasttm(L, udata->uv.metatable, TM_GC);
+		  if (tm != NULL) {
+			  lu_byte oldah = L->allowhook;
+			  lu_mem oldt = g->GCthreshold;
+			  L->allowhook = 0;  /* stop debug hooks during GC tag method */
+			  g->GCthreshold = 2*g->totalbytes;  /* avoid GC steps */
+			  setobj2s(L, L->top, tm);
+			  setuvalue(L, L->top+1, udata);
+			  L->top += 2;
+			  luaD_call(L, L->top - 2, 0);
+			  L->allowhook = oldah;  /* restore hooks */
+			  g->GCthreshold = oldt;  /* restore threshold */
+		  }
+      #endif
+
       luaM_freemem(L, o, sizeudata(gco2u(o)));
       break;
     }
@@ -543,7 +560,11 @@
   g->gray = g->grayagain;
   g->grayagain = NULL;
   propagateall(g);
- udsize = luaC_separateudata(L, 0); /* separate userdata to be finalized */
+  #ifdef LUA_SIMPLE_FINALIZERS
+	udsize = 0;
+  #else
+ udsize = luaC_separateudata(L, 0); /* separate userdata to be finalized */
+  #endif
   marktmu(g);  /* mark `preserved' userdata */
   udsize += propagateall(g);  /* remark, to propagate `preserveness' */
   cleartable(g->weak);  /* remove collected objects from weak tables */
Index: lua/src/lstate.c
===================================================================
--- lua/src/lstate.c	(revision 4140)
+++ lua/src/lstate.c	(working copy)
@@ -200,7 +200,11 @@
   L = G(L)->mainthread;  /* only the main thread can be closed */
   lua_lock(L);
   luaF_close(L, L->stack);  /* close all upvalues for this thread */
-  luaC_separateudata(L, 1);  /* separate udata that have GC metamethods */
+  #ifdef LUA_SIMPLE_FINALIZERS
+    ;
+  #else
+ luaC_separateudata(L, 1); /* separate udata that have GC metamethods */
+  #endif
   L->errfunc = 0;  /* no error function during GC metamethods */
   do {  /* repeat until no more errors */
     L->ci = L->base_ci;
Index: lua/src/luaconf.h
===================================================================
--- lua/src/luaconf.h	(revision 4140)
+++ lua/src/luaconf.h	(working copy)
@@ -34,6 +34,10 @@
 	#define LUASYSTEM(x) system(x)
 #endif

+/* GRIN: Skip luas complicated handling of finalizers and call them directly when the
+   userdata is destroyed, to get rid of the stall in atomic(). */
+#define LUA_SIMPLE_FINALIZERS
+
 /*
 @@ LUA_ANSI controls the use of non-ansi features.
 ** CHANGE it (define it) if you want Lua to avoid the use of any

// Niklas