lua-users home
lua-l archive

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


Roberto Ierusalimschy <roberto@inf.puc-rio.br> 于2021年12月28日周二 02:25写道:
>
> > Roberto Ierusalimschy <roberto@inf.puc-rio.br> 于2021年12月22日周三 01:56写道:
> > >
> > > Serious?  This bug is there for more than 10 years, and you wait to
> > > announce it one minute after we announce a new release candidate?
> >
> > I saw the patch
> > https://github.com/lua/lua/commit/597a53bbc681089d85b082b46c2e2428dec43b86,
> >  It seems that we can't create a new finalizer when closing state.
> >
> > I think we can link the new finalizer at the beginning of 'tobefnz'
> > list immediately when closing state.  The finalizer of _CLIBS is at
> > the end, so it can avoid this issue.
>
> I am not sure what is your point. Does the patch do not solve the
> problem? Is it too restrictive? Too complex?

It's restrictive in my opinion, the limitation is unnecessary.

Maybe there is a better solution :

diff --git a/lgc.c b/lgc.c
index 42a73d81..30a138d2 100644
--- a/lgc.c
+++ b/lgc.c
@@ -1011,9 +1011,8 @@ static void correctpointers (global_State *g,
GCObject *o) {
 void luaC_checkfinalizer (lua_State *L, GCObject *o, Table *mt) {
   global_State *g = G(L);
   if (tofinalize(o) ||                 /* obj. is already marked... */
-      gfasttm(g, mt, TM_GC) == NULL ||    /* or has no finalizer... */
-      (g->gcstp & GCSTPCLS))                   /* or closing state? */
-    return;  /* nothing to be done */
+      gfasttm(g, mt, TM_GC) == NULL)    /* or has no finalizer... */
+      return;   /* nothing to be done */
   else {  /* move 'o' to 'finobj' list */
     GCObject **p;
     if (issweepphase(g)) {
@@ -1026,8 +1025,13 @@ void luaC_checkfinalizer (lua_State *L,
GCObject *o, Table *mt) {
     /* search for pointer pointing to 'o' */
     for (p = &g->allgc; *p != o; p = &(*p)->next) { /* empty */ }
     *p = o->next;  /* remove 'o' from 'allgc' list */
-    o->next = g->finobj;  /* link it in 'finobj' list */
-    g->finobj = o;
+    if (g->gcstp & GCSTPCLS) {                   /* closing state? */
+      o->next = g->tobefnz;
+      g->tobefnz = o;
+    } else {
+      o->next = g->finobj;  /* link it in 'finobj' list */
+      g->finobj = o;
+    }
     l_setbit(o->marked, FINALIZEDBIT);  /* mark it as such */
   }
 }
@@ -1503,10 +1507,10 @@ static void deletelist (lua_State *L, GCObject
*p, GCObject *limit) {
 */
 void luaC_freeallobjects (lua_State *L) {
   global_State *g = G(L);
-  g->gcstp = GCSTPCLS;  /* no extra finalizers after here */
   luaC_changemode(L, KGC_INC);
   separatetobefnz(g, 1);  /* separate all objects with finalizers */
   lua_assert(g->finobj == NULL);
+  g->gcstp = GCSTPCLS;
   callallpendingfinalizers(L);
   deletelist(L, g->allgc, obj2gco(g->mainthread));
   lua_assert(g->finobj == NULL);  /* no new finalizers */

We can link the finalizer to tobefnz list when closing state, because
all the objects will be collected immediately. We don't need wait them
in next GC cycle.

setmetatable({},{__gc=function()
         -- Called as last finalizer during os.exit(0, true)
         tl.test()
     end})

This can be run in correct order (before the finalizer of _CLIBS)
rather than ignore it.

-- 
http://blog.codingnow.com