From 0bfc572e51d9035a615ef6e9523f736c9ffa8e57 Mon Sep 17 00:00:00 2001 From: Roberto Ierusalimschy Date: Mon, 13 Dec 2021 10:41:17 -0300 Subject: Bug: GC is not reentrant As the GC is not reentrant, finalizers should not be able to invoke it. --- lgc.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) (limited to 'lgc.c') diff --git a/lgc.c b/lgc.c index b360eed0..7d0b5e4f 100644 --- a/lgc.c +++ b/lgc.c @@ -906,16 +906,16 @@ static void GCTM (lua_State *L) { if (!notm(tm)) { /* is there a finalizer? */ int status; lu_byte oldah = L->allowhook; - int running = g->gcrunning; + int oldgcstp = g->gcstp; + g->gcstp = GCSTPGC; /* avoid GC steps */ L->allowhook = 0; /* stop debug hooks during GC metamethod */ - g->gcrunning = 0; /* avoid GC steps */ setobj2s(L, L->top++, tm); /* push finalizer... */ setobj2s(L, L->top++, &v); /* ... and its argument */ L->ci->callstatus |= CIST_FIN; /* will run a finalizer */ status = luaD_pcall(L, dothecall, NULL, savestack(L, L->top - 2), 0); L->ci->callstatus &= ~CIST_FIN; /* not running a finalizer anymore */ L->allowhook = oldah; /* restore hooks */ - g->gcrunning = running; /* restore state */ + g->gcstp = oldgcstp; /* restore state */ if (l_unlikely(status != LUA_OK)) { /* error while running __gc? */ luaE_warnerror(L, "__gc metamethod"); L->top--; /* pops error object */ @@ -1502,9 +1502,11 @@ static void deletelist (lua_State *L, GCObject *p, GCObject *limit) { */ void luaC_freeallobjects (lua_State *L) { global_State *g = G(L); + g->gcstp = GCSTPGC; luaC_changemode(L, KGC_INC); separatetobefnz(g, 1); /* separate all objects with finalizers */ lua_assert(g->finobj == NULL); + g->gcstp = 0; callallpendingfinalizers(L); deletelist(L, g->allgc, obj2gco(g->mainthread)); deletelist(L, g->finobj, NULL); @@ -1647,6 +1649,7 @@ void luaC_runtilstate (lua_State *L, int statesmask) { } + /* ** Performs a basic incremental step. The debt and step size are ** converted from bytes to "units of work"; then the function loops @@ -1678,7 +1681,7 @@ static void incstep (lua_State *L, global_State *g) { void luaC_step (lua_State *L) { global_State *g = G(L); lua_assert(!g->gcemergency); - if (g->gcrunning) { /* running? */ + if (gcrunning(g)) { /* running? */ if(isdecGCmodegen(g)) genstep(L, g); else -- cgit v1.2.3-55-g6feb