forked from pool/lua54
Accepting request 943308 from devel:languages:lua
- Re-enable readline support in Lua, the way to do this changed in Lua 5.4 - Because we are linking with readline add GPLv3+ only to the main package - Subsequently, update main_test.patch to ignore another test - Update upstream-bugs.patch and upstream-bugs-test.patch to fix bugs 9,10,12 for build and tests respectively. Bug 11 changes interface of luaD_pretailcall. OBS-URL: https://build.opensuse.org/request/show/943308 OBS-URL: https://build.opensuse.org/package/show/openSUSE:Factory/lua54?expand=0&rev=14
This commit is contained in:
commit
84bcbbf713
@ -1,3 +1,19 @@
|
|||||||
|
-------------------------------------------------------------------
|
||||||
|
Thu Dec 30 18:34:01 UTC 2021 - Callum Farmer <gmbr3@opensuse.org>
|
||||||
|
|
||||||
|
- Re-enable readline support in Lua, the way to do this changed
|
||||||
|
in Lua 5.4
|
||||||
|
- Because we are linking with readline add GPLv3+ only to the
|
||||||
|
main package
|
||||||
|
- Subsequently, update main_test.patch to ignore another test
|
||||||
|
|
||||||
|
-------------------------------------------------------------------
|
||||||
|
Thu Dec 30 13:41:04 UTC 2021 - Callum Farmer <gmbr3@opensuse.org>
|
||||||
|
|
||||||
|
- Update upstream-bugs.patch and upstream-bugs-test.patch to fix
|
||||||
|
bugs 9,10,12 for build and tests respectively. Bug 11 changes
|
||||||
|
interface of luaD_pretailcall.
|
||||||
|
|
||||||
-------------------------------------------------------------------
|
-------------------------------------------------------------------
|
||||||
Sat Nov 27 16:54:20 UTC 2021 - Callum Farmer <gmbr3@opensuse.org>
|
Sat Nov 27 16:54:20 UTC 2021 - Callum Farmer <gmbr3@opensuse.org>
|
||||||
|
|
||||||
|
14
lua54.spec
14
lua54.spec
@ -29,7 +29,7 @@ Name: lua54%{name_ext}
|
|||||||
Version: 5.4.3
|
Version: 5.4.3
|
||||||
Release: 0
|
Release: 0
|
||||||
Summary: Small Embeddable Language with Procedural Syntax
|
Summary: Small Embeddable Language with Procedural Syntax
|
||||||
License: MIT
|
License: GPL-3.0-or-later
|
||||||
Group: Development/Languages/Other
|
Group: Development/Languages/Other
|
||||||
URL: http://www.lua.org
|
URL: http://www.lua.org
|
||||||
Source: http://www.lua.org/ftp/lua-%{version}.tar.gz
|
Source: http://www.lua.org/ftp/lua-%{version}.tar.gz
|
||||||
@ -74,6 +74,7 @@ of C functions, written in ANSI C.
|
|||||||
|
|
||||||
%package devel
|
%package devel
|
||||||
Summary: Development files for lua
|
Summary: Development files for lua
|
||||||
|
License: MIT
|
||||||
Group: Development/Libraries/C and C++
|
Group: Development/Libraries/C and C++
|
||||||
Requires: %{libname} = %{version}
|
Requires: %{libname} = %{version}
|
||||||
Requires: %{name} = %{version}
|
Requires: %{name} = %{version}
|
||||||
@ -94,6 +95,7 @@ application.
|
|||||||
|
|
||||||
%package -n %{libname}
|
%package -n %{libname}
|
||||||
Summary: The Lua integration library
|
Summary: The Lua integration library
|
||||||
|
License: MIT
|
||||||
Group: System/Libraries
|
Group: System/Libraries
|
||||||
# Compat as libtool changes the soname
|
# Compat as libtool changes the soname
|
||||||
%ifarch aarch64 x86_64 ppc64 ppc64le s390x riscv64
|
%ifarch aarch64 x86_64 ppc64 ppc64le s390x riscv64
|
||||||
@ -120,6 +122,7 @@ of C functions, written in ANSI C.
|
|||||||
|
|
||||||
%package doc
|
%package doc
|
||||||
Summary: Documentation for Lua, a small embeddable language
|
Summary: Documentation for Lua, a small embeddable language
|
||||||
|
License: MIT
|
||||||
Group: Documentation/HTML
|
Group: Documentation/HTML
|
||||||
BuildArch: noarch
|
BuildArch: noarch
|
||||||
Supplements: (lua54 and patterns-base-documentation)
|
Supplements: (lua54 and patterns-base-documentation)
|
||||||
@ -157,17 +160,14 @@ cat doc/luac.1 | sed 's/TH LUAC 1/TH LUAC%{major_version} 1/' > doc/luac%{major_
|
|||||||
|
|
||||||
%build
|
%build
|
||||||
sed -i -e "s@lib/lua/@%{_lib}/lua/@g" src/luaconf.h
|
sed -i -e "s@lib/lua/@%{_lib}/lua/@g" src/luaconf.h
|
||||||
make %{_smp_mflags} VERBOSE=1 -C src \
|
make linux-readline %{_smp_mflags} VERBOSE=1 -C src \
|
||||||
CC="cc" \
|
CC="cc" \
|
||||||
MYCFLAGS="%{optflags} -std=gnu99 -D_GNU_SOURCE -fPIC -DLUA_USE_LINUX -DLUA_COMPAT_MODULE" \
|
MYCFLAGS="%{optflags} -std=gnu99 -D_GNU_SOURCE -fPIC -DLUA_COMPAT_MODULE" \
|
||||||
MYLIBS="-Wl,-E -ldl -lreadline -lhistory -lncurses" \
|
|
||||||
V=%{major_version} \
|
V=%{major_version} \
|
||||||
LIBTOOL="libtool --quiet" \
|
LIBTOOL="libtool --quiet"
|
||||||
all
|
|
||||||
|
|
||||||
%install
|
%install
|
||||||
%make_install \
|
%make_install \
|
||||||
V=%{major_version} \
|
|
||||||
LIBTOOL="libtool --quiet" \
|
LIBTOOL="libtool --quiet" \
|
||||||
INSTALL_TOP="%{buildroot}%{_prefix}" \
|
INSTALL_TOP="%{buildroot}%{_prefix}" \
|
||||||
INSTALL_LIB="%{buildroot}%{_libdir}"
|
INSTALL_LIB="%{buildroot}%{_libdir}"
|
||||||
|
@ -1,5 +1,14 @@
|
|||||||
--- a/main.lua
|
--- a/main.lua
|
||||||
+++ b/main.lua
|
+++ b/main.lua
|
||||||
|
@@ -47,7 +47,7 @@
|
||||||
|
assert(string.sub(s, -1) == "\n")
|
||||||
|
local t = getoutput()
|
||||||
|
for line in string.gmatch(s, ".-\n") do
|
||||||
|
- assert(string.find(t, line, 1, true))
|
||||||
|
+ -- assert(string.find(t, line, 1, true))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
@@ -307,11 +307,11 @@
|
@@ -307,11 +307,11 @@
|
||||||
]]
|
]]
|
||||||
RUN([[lua -e "%s" -i < %s > %s]], prompt, prog, out)
|
RUN([[lua -e "%s" -i < %s > %s]], prompt, prog, out)
|
||||||
|
@ -287,3 +287,84 @@ index 461e03770..76c9d6e63 100644
|
|||||||
-- attempt to resume 'normal' coroutine
|
-- attempt to resume 'normal' coroutine
|
||||||
local co1, co2
|
local co1, co2
|
||||||
co1 = coroutine.create(function () return co2() end)
|
co1 = coroutine.create(function () return co2() end)
|
||||||
|
diff --git a/testes/api.lua b/testes/api.lua
|
||||||
|
index c1bcb4b7b..bd85a923c 100644
|
||||||
|
--- a/api.lua
|
||||||
|
+++ b/api.lua
|
||||||
|
@@ -804,15 +804,14 @@ F = function (x)
|
||||||
|
d = nil
|
||||||
|
assert(debug.getmetatable(x).__gc == F)
|
||||||
|
assert(load("table.insert({}, {})"))() -- create more garbage
|
||||||
|
- collectgarbage() -- force a GC during GC
|
||||||
|
- assert(debug.getmetatable(x).__gc == F) -- previous GC did not mess this?
|
||||||
|
+ assert(not collectgarbage()) -- GC during GC (no op)
|
||||||
|
local dummy = {} -- create more garbage during GC
|
||||||
|
if A ~= nil then
|
||||||
|
assert(type(A) == "userdata")
|
||||||
|
assert(T.udataval(A) == B)
|
||||||
|
debug.getmetatable(A) -- just access it
|
||||||
|
end
|
||||||
|
- A = x -- ressucita userdata
|
||||||
|
+ A = x -- ressurect userdata
|
||||||
|
B = udval
|
||||||
|
return 1,2,3
|
||||||
|
end
|
||||||
|
diff --git a/testes/gc.lua b/testes/gc.lua
|
||||||
|
index 2332c939a..d865cb28d 100644
|
||||||
|
--- a/gc.lua
|
||||||
|
+++ b/gc.lua
|
||||||
|
@@ -676,11 +676,13 @@ end
|
||||||
|
-- just to make sure
|
||||||
|
assert(collectgarbage'isrunning')
|
||||||
|
|
||||||
|
-do -- check that the collector is reentrant in incremental mode
|
||||||
|
+do -- check that the collector is not reentrant in incremental mode
|
||||||
|
+ local res = true
|
||||||
|
setmetatable({}, {__gc = function ()
|
||||||
|
- collectgarbage()
|
||||||
|
+ res = collectgarbage()
|
||||||
|
end})
|
||||||
|
collectgarbage()
|
||||||
|
+ assert(not res)
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
diff --git a/testes/main.lua b/testes/main.lua
|
||||||
|
index 52c779541..9def63860 100644
|
||||||
|
--- a/main.lua
|
||||||
|
+++ b/main.lua
|
||||||
|
@@ -261,6 +261,34 @@ u2 = setmetatable({}, {__gc = function () error("ZYX") end})
|
||||||
|
RUN('lua -W %s 2> %s', prog, out)
|
||||||
|
checkprogout("ZYX)\nXYZ)\n")
|
||||||
|
|
||||||
|
+-- bug since 5.2: finalizer called when closing a state could
|
||||||
|
+-- subvert finalization order
|
||||||
|
+prepfile[[
|
||||||
|
+-- should be called last
|
||||||
|
+print("creating 1")
|
||||||
|
+setmetatable({}, {__gc = function () print(1) end})
|
||||||
|
+
|
||||||
|
+print("creating 2")
|
||||||
|
+setmetatable({}, {__gc = function ()
|
||||||
|
+ print("2")
|
||||||
|
+ print("creating 3")
|
||||||
|
+ -- this finalizer should not be called, as object will be
|
||||||
|
+ -- created after 'lua_close' has been called
|
||||||
|
+ setmetatable({}, {__gc = function () print(3) end})
|
||||||
|
+ print(collectgarbage()) -- cannot call collector here
|
||||||
|
+ os.exit(0, true)
|
||||||
|
+end})
|
||||||
|
+]]
|
||||||
|
+RUN('lua -W %s > %s', prog, out)
|
||||||
|
+checkout[[
|
||||||
|
+creating 1
|
||||||
|
+creating 2
|
||||||
|
+2
|
||||||
|
+creating 3
|
||||||
|
+nil
|
||||||
|
+1
|
||||||
|
+]]
|
||||||
|
+
|
||||||
|
|
||||||
|
-- test many arguments
|
||||||
|
prepfile[[print(({...})[30])]]
|
||||||
|
@ -325,3 +325,341 @@ index bfc590262..5cb0847c8 100644
|
|||||||
luaD_reallocstack(L, cast_int(ci->top - L->stack), 0);
|
luaD_reallocstack(L, cast_int(ci->top - L->stack), 0);
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
From 1de95e97ef65632a88e08b6184bd9d1ceba7ec2f Mon Sep 17 00:00:00 2001
|
||||||
|
From: Roberto Ierusalimschy <roberto@inf.puc-rio.br>
|
||||||
|
Date: Fri, 10 Dec 2021 10:53:54 -0300
|
||||||
|
Subject: [PATCH] Bug: Lua stack still active when closing a state
|
||||||
|
|
||||||
|
---
|
||||||
|
lstate.c | 1 +
|
||||||
|
1 file changed, 1 insertion(+)
|
||||||
|
|
||||||
|
diff --git a/lstate.c b/lstate.c
|
||||||
|
index 5cb0847c8..547a7a014 100644
|
||||||
|
--- a/src/lstate.c
|
||||||
|
+++ b/src/lstate.c
|
||||||
|
@@ -271,6 +271,7 @@ static void close_state (lua_State *L) {
|
||||||
|
if (!completestate(g)) /* closing a partially built state? */
|
||||||
|
luaC_freeallobjects(L); /* jucst collect its objects */
|
||||||
|
else { /* closing a fully built state */
|
||||||
|
+ L->ci = &L->base_ci; /* unwind CallInfo list */
|
||||||
|
luaD_closeprotected(L, 1, LUA_OK); /* close all upvalues */
|
||||||
|
luaC_freeallobjects(L); /* collect all objects */
|
||||||
|
luai_userstateclose(L);
|
||||||
|
From 0bfc572e51d9035a615ef6e9523f736c9ffa8e57 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Roberto Ierusalimschy <roberto@inf.puc-rio.br>
|
||||||
|
Date: Mon, 13 Dec 2021 10:41:17 -0300
|
||||||
|
Subject: [PATCH] Bug: GC is not reentrant
|
||||||
|
|
||||||
|
As the GC is not reentrant, finalizers should not be able to invoke it.
|
||||||
|
---
|
||||||
|
lapi.c | 17 +++++++++--------
|
||||||
|
lbaselib.c | 19 +++++++++++++++++--
|
||||||
|
lgc.c | 11 +++++++----
|
||||||
|
lgc.h | 9 +++++++++
|
||||||
|
lstate.c | 4 ++--
|
||||||
|
lstate.h | 2 +-
|
||||||
|
manual/manual.of | 11 ++++++-----
|
||||||
|
testes/api.lua | 5 ++---
|
||||||
|
testes/gc.lua | 6 ++++--
|
||||||
|
9 files changed, 57 insertions(+), 27 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/lapi.c b/lapi.c
|
||||||
|
index 071a06f3d..3585ac436 100644
|
||||||
|
--- a/src/lapi.c
|
||||||
|
+++ b/src/lapi.c
|
||||||
|
@@ -1136,18 +1136,19 @@ LUA_API int lua_status (lua_State *L) {
|
||||||
|
LUA_API int lua_gc (lua_State *L, int what, ...) {
|
||||||
|
va_list argp;
|
||||||
|
int res = 0;
|
||||||
|
- global_State *g;
|
||||||
|
+ global_State *g = G(L);
|
||||||
|
+ if (g->gcstp & GCSTPGC) /* internal stop? */
|
||||||
|
+ return -1; /* all options are invalid when stopped */
|
||||||
|
lua_lock(L);
|
||||||
|
- g = G(L);
|
||||||
|
va_start(argp, what);
|
||||||
|
switch (what) {
|
||||||
|
case LUA_GCSTOP: {
|
||||||
|
- g->gcrunning = 0;
|
||||||
|
+ g->gcstp = GCSTPUSR; /* stopeed by the user */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case LUA_GCRESTART: {
|
||||||
|
luaE_setdebt(g, 0);
|
||||||
|
- g->gcrunning = 1;
|
||||||
|
+ g->gcstp = 0; /* (GCSTPGC must be already zero here) */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case LUA_GCCOLLECT: {
|
||||||
|
@@ -1166,8 +1167,8 @@ LUA_API int lua_gc (lua_State *L, int what, ...) {
|
||||||
|
case LUA_GCSTEP: {
|
||||||
|
int data = va_arg(argp, int);
|
||||||
|
l_mem debt = 1; /* =1 to signal that it did an actual step */
|
||||||
|
- lu_byte oldrunning = g->gcrunning;
|
||||||
|
- g->gcrunning = 1; /* allow GC to run */
|
||||||
|
+ lu_byte oldstp = g->gcstp;
|
||||||
|
+ g->gcstp = 0; /* allow GC to run (GCSTPGC must be zero here) */
|
||||||
|
if (data == 0) {
|
||||||
|
luaE_setdebt(g, 0); /* do a basic step */
|
||||||
|
luaC_step(L);
|
||||||
|
@@ -1177,7 +1178,7 @@ LUA_API int lua_gc (lua_State *L, int what, ...) {
|
||||||
|
luaE_setdebt(g, debt);
|
||||||
|
luaC_checkGC(L);
|
||||||
|
}
|
||||||
|
- g->gcrunning = oldrunning; /* restore previous state */
|
||||||
|
+ g->gcstp = oldstp; /* restore previous state */
|
||||||
|
if (debt > 0 && g->gcstate == GCSpause) /* end of cycle? */
|
||||||
|
res = 1; /* signal it */
|
||||||
|
break;
|
||||||
|
@@ -1195,7 +1196,7 @@ LUA_API int lua_gc (lua_State *L, int what, ...) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case LUA_GCISRUNNING: {
|
||||||
|
- res = g->gcrunning;
|
||||||
|
+ res = gcrunning(g);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case LUA_GCGEN: {
|
||||||
|
diff --git a/lbaselib.c b/lbaselib.c
|
||||||
|
index 912c4cc63..1d60c9ded 100644
|
||||||
|
--- a/src/lbaselib.c
|
||||||
|
+++ b/src/lbaselib.c
|
||||||
|
@@ -182,12 +182,20 @@ static int luaB_rawset (lua_State *L) {
|
||||||
|
|
||||||
|
|
||||||
|
static int pushmode (lua_State *L, int oldmode) {
|
||||||
|
- lua_pushstring(L, (oldmode == LUA_GCINC) ? "incremental"
|
||||||
|
- : "generational");
|
||||||
|
+ if (oldmode == -1)
|
||||||
|
+ luaL_pushfail(L); /* invalid call to 'lua_gc' */
|
||||||
|
+ else
|
||||||
|
+ lua_pushstring(L, (oldmode == LUA_GCINC) ? "incremental"
|
||||||
|
+ : "generational");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
+/*
|
||||||
|
+** check whether call to 'lua_gc' was valid (not inside a finalizer)
|
||||||
|
+*/
|
||||||
|
+#define checkvalres(res) { if (res == -1) break; }
|
||||||
|
+
|
||||||
|
static int luaB_collectgarbage (lua_State *L) {
|
||||||
|
static const char *const opts[] = {"stop", "restart", "collect",
|
||||||
|
"count", "step", "setpause", "setstepmul",
|
||||||
|
@@ -200,12 +208,14 @@ static int luaB_collectgarbage (lua_State *L) {
|
||||||
|
case LUA_GCCOUNT: {
|
||||||
|
int k = lua_gc(L, o);
|
||||||
|
int b = lua_gc(L, LUA_GCCOUNTB);
|
||||||
|
+ checkvalres(k);
|
||||||
|
lua_pushnumber(L, (lua_Number)k + ((lua_Number)b/1024));
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
case LUA_GCSTEP: {
|
||||||
|
int step = (int)luaL_optinteger(L, 2, 0);
|
||||||
|
int res = lua_gc(L, o, step);
|
||||||
|
+ checkvalres(res);
|
||||||
|
lua_pushboolean(L, res);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
@@ -213,11 +223,13 @@ static int luaB_collectgarbage (lua_State *L) {
|
||||||
|
case LUA_GCSETSTEPMUL: {
|
||||||
|
int p = (int)luaL_optinteger(L, 2, 0);
|
||||||
|
int previous = lua_gc(L, o, p);
|
||||||
|
+ checkvalres(previous);
|
||||||
|
lua_pushinteger(L, previous);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
case LUA_GCISRUNNING: {
|
||||||
|
int res = lua_gc(L, o);
|
||||||
|
+ checkvalres(res);
|
||||||
|
lua_pushboolean(L, res);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
@@ -234,10 +246,13 @@ static int luaB_collectgarbage (lua_State *L) {
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
int res = lua_gc(L, o);
|
||||||
|
+ checkvalres(res);
|
||||||
|
lua_pushinteger(L, res);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
+ luaL_pushfail(L); /* invalid call (inside a finalizer) */
|
||||||
|
+ return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
diff --git a/lgc.c b/lgc.c
|
||||||
|
index b360eed00..7d0b5e4f7 100644
|
||||||
|
--- a/src/lgc.c
|
||||||
|
+++ b/src/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
|
||||||
|
diff --git a/lgc.h b/lgc.h
|
||||||
|
index 073e2a402..024a4328e 100644
|
||||||
|
--- a/src/lgc.h
|
||||||
|
+++ b/src/lgc.h
|
||||||
|
@@ -148,6 +148,15 @@
|
||||||
|
*/
|
||||||
|
#define isdecGCmodegen(g) (g->gckind == KGC_GEN || g->lastatomic != 0)
|
||||||
|
|
||||||
|
+
|
||||||
|
+/*
|
||||||
|
+** Control when GC is running:
|
||||||
|
+*/
|
||||||
|
+#define GCSTPUSR 1 /* bit true when GC stopped by user */
|
||||||
|
+#define GCSTPGC 2 /* bit true when GC stopped by itself */
|
||||||
|
+#define gcrunning(g) ((g)->gcstp == 0)
|
||||||
|
+
|
||||||
|
+
|
||||||
|
/*
|
||||||
|
** Does one step of collection when debt becomes positive. 'pre'/'pos'
|
||||||
|
** allows some adjustments to be done only when needed. macro
|
||||||
|
diff --git a/lstate.c b/lstate.c
|
||||||
|
index 547a7a014..1ffe1a0f7 100644
|
||||||
|
--- a/src/lstate.c
|
||||||
|
+++ b/src/lstate.c
|
||||||
|
@@ -236,7 +236,7 @@ static void f_luaopen (lua_State *L, void *ud) {
|
||||||
|
luaS_init(L);
|
||||||
|
luaT_init(L);
|
||||||
|
luaX_init(L);
|
||||||
|
- g->gcrunning = 1; /* allow gc */
|
||||||
|
+ g->gcstp = 0; /* allow gc */
|
||||||
|
setnilvalue(&g->nilvalue); /* now state is complete */
|
||||||
|
luai_userstateopen(L);
|
||||||
|
}
|
||||||
|
@@ -373,7 +373,7 @@ LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud) {
|
||||||
|
g->ud_warn = NULL;
|
||||||
|
g->mainthread = L;
|
||||||
|
g->seed = luai_makeseed(L);
|
||||||
|
- g->gcrunning = 0; /* no GC while building state */
|
||||||
|
+ g->gcstp = GCSTPGC; /* no GC while building state */
|
||||||
|
g->strt.size = g->strt.nuse = 0;
|
||||||
|
g->strt.hash = NULL;
|
||||||
|
setnilvalue(&g->l_registry);
|
||||||
|
diff --git a/lstate.h b/lstate.h
|
||||||
|
index 44cf939cb..7886d8914 100644
|
||||||
|
--- a/src/lstate.h
|
||||||
|
+++ b/src/lstate.h
|
||||||
|
@@ -263,7 +263,7 @@ typedef struct global_State {
|
||||||
|
lu_byte gcstopem; /* stops emergency collections */
|
||||||
|
lu_byte genminormul; /* control for minor generational collections */
|
||||||
|
lu_byte genmajormul; /* control for major generational collections */
|
||||||
|
- lu_byte gcrunning; /* true if GC is running */
|
||||||
|
+ lu_byte gcstp; /* control whether GC is running */
|
||||||
|
lu_byte gcemergency; /* true if this is an emergency collection */
|
||||||
|
lu_byte gcpause; /* size of pause between successive GCs */
|
||||||
|
lu_byte gcstepmul; /* GC "speed" */
|
||||||
|
From 597a53bbc681089d85b082b46c2e2428dec43b86 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Roberto Ierusalimschy <roberto@inf.puc-rio.br>
|
||||||
|
Date: Wed, 22 Dec 2021 09:00:52 -0300
|
||||||
|
Subject: [PATCH] Bug: finalizer calling exit can corrupt finalization order
|
||||||
|
|
||||||
|
'os.exit' can call lua_close again, separating new finalizers
|
||||||
|
created after all previous finalizers were already separated.
|
||||||
|
---
|
||||||
|
lgc.c | 10 +++++-----
|
||||||
|
lgc.h | 1 +
|
||||||
|
testes/main.lua | 28 ++++++++++++++++++++++++++++
|
||||||
|
3 files changed, 34 insertions(+), 5 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/lgc.c b/lgc.c
|
||||||
|
index d3f5b5b7b..42a73d813 100644
|
||||||
|
--- a/src/lgc.c
|
||||||
|
+++ b/src/lgc.c
|
||||||
|
@@ -907,7 +907,7 @@ static void GCTM (lua_State *L) {
|
||||||
|
int status;
|
||||||
|
lu_byte oldah = L->allowhook;
|
||||||
|
int oldgcstp = g->gcstp;
|
||||||
|
- g->gcstp = GCSTPGC; /* avoid GC steps */
|
||||||
|
+ g->gcstp |= GCSTPGC; /* avoid GC steps */
|
||||||
|
L->allowhook = 0; /* stop debug hooks during GC metamethod */
|
||||||
|
setobj2s(L, L->top++, tm); /* push finalizer... */
|
||||||
|
setobj2s(L, L->top++, &v); /* ... and its argument */
|
||||||
|
@@ -1011,7 +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? */
|
||||||
|
+ gfasttm(g, mt, TM_GC) == NULL || /* or has no finalizer... */
|
||||||
|
+ (g->gcstp & GCSTPCLS)) /* or closing state? */
|
||||||
|
return; /* nothing to be done */
|
||||||
|
else { /* move 'o' to 'finobj' list */
|
||||||
|
GCObject **p;
|
||||||
|
@@ -1502,14 +1503,13 @@ static void deletelist (lua_State *L, GCObject *p, GCObject *limit) {
|
||||||
|
*/
|
||||||
|
void luaC_freeallobjects (lua_State *L) {
|
||||||
|
global_State *g = G(L);
|
||||||
|
- g->gcstp = GCSTPGC;
|
||||||
|
+ 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 = 0;
|
||||||
|
callallpendingfinalizers(L);
|
||||||
|
deletelist(L, g->allgc, obj2gco(g->mainthread));
|
||||||
|
- deletelist(L, g->finobj, NULL);
|
||||||
|
+ lua_assert(g->finobj == NULL); /* no new finalizers */
|
||||||
|
deletelist(L, g->fixedgc, NULL); /* collect fixed objects */
|
||||||
|
lua_assert(g->strt.nuse == 0);
|
||||||
|
}
|
||||||
|
diff --git a/lgc.h b/lgc.h
|
||||||
|
index 024a4328e..4a125634b 100644
|
||||||
|
--- a/src/lgc.h
|
||||||
|
+++ b/src/lgc.h
|
||||||
|
@@ -154,6 +154,7 @@
|
||||||
|
*/
|
||||||
|
#define GCSTPUSR 1 /* bit true when GC stopped by user */
|
||||||
|
#define GCSTPGC 2 /* bit true when GC stopped by itself */
|
||||||
|
+#define GCSTPCLS 4 /* bit true when closing Lua state */
|
||||||
|
#define gcrunning(g) ((g)->gcstp == 0)
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user