diff options
| author | Roberto I <roberto@inf.puc-rio.br> | 2025-12-13 16:16:59 -0300 |
|---|---|---|
| committer | Roberto I <roberto@inf.puc-rio.br> | 2025-12-13 16:16:59 -0300 |
| commit | a5522f06d2679b8f18534fd6a9968f7eb539dc31 (patch) | |
| tree | 65275619e7829b569bfb18dea624358aa17dbc91 | |
| parent | 3d03ae5bd6314f27c8635e06ec363150c2c19062 (diff) | |
| download | lua-a5522f06d2679b8f18534fd6a9968f7eb539dc31.tar.gz lua-a5522f06d2679b8f18534fd6a9968f7eb539dc31.tar.bz2 lua-a5522f06d2679b8f18534fd6a9968f7eb539dc31.zip | |
If the stack does not have some minimum available space, the GC defers
calling a finalizer until the next cycle. That avoids errors while
running a finalizer that the programmer cannot control.
| -rw-r--r-- | ldo.c | 11 | ||||
| -rw-r--r-- | ldo.h | 1 | ||||
| -rw-r--r-- | lgc.c | 7 |
3 files changed, 16 insertions, 3 deletions
| @@ -221,6 +221,17 @@ l_noret luaD_errerr (lua_State *L) { | |||
| 221 | 221 | ||
| 222 | 222 | ||
| 223 | /* | 223 | /* |
| 224 | ** Check whether stack has enough space to run a simple function (such | ||
| 225 | ** as a finalizer): At least BASIC_STACK_SIZE in the Lua stack and | ||
| 226 | ** 2 slots in the C stack. | ||
| 227 | */ | ||
| 228 | int luaD_checkminstack (lua_State *L) { | ||
| 229 | return ((stacksize(L) < MAXSTACK - BASIC_STACK_SIZE) && | ||
| 230 | (getCcalls(L) < LUAI_MAXCCALLS - 2)); | ||
| 231 | } | ||
| 232 | |||
| 233 | |||
| 234 | /* | ||
| 224 | ** In ISO C, any pointer use after the pointer has been deallocated is | 235 | ** In ISO C, any pointer use after the pointer has been deallocated is |
| 225 | ** undefined behavior. So, before a stack reallocation, all pointers | 236 | ** undefined behavior. So, before a stack reallocation, all pointers |
| 226 | ** should be changed to offsets, and after the reallocation they should | 237 | ** should be changed to offsets, and after the reallocation they should |
| @@ -89,6 +89,7 @@ LUAI_FUNC int luaD_reallocstack (lua_State *L, int newsize, int raiseerror); | |||
| 89 | LUAI_FUNC int luaD_growstack (lua_State *L, int n, int raiseerror); | 89 | LUAI_FUNC int luaD_growstack (lua_State *L, int n, int raiseerror); |
| 90 | LUAI_FUNC void luaD_shrinkstack (lua_State *L); | 90 | LUAI_FUNC void luaD_shrinkstack (lua_State *L); |
| 91 | LUAI_FUNC void luaD_inctop (lua_State *L); | 91 | LUAI_FUNC void luaD_inctop (lua_State *L); |
| 92 | LUAI_FUNC int luaD_checkminstack (lua_State *L); | ||
| 92 | 93 | ||
| 93 | LUAI_FUNC l_noret luaD_throw (lua_State *L, TStatus errcode); | 94 | LUAI_FUNC l_noret luaD_throw (lua_State *L, TStatus errcode); |
| 94 | LUAI_FUNC l_noret luaD_throwbaselevel (lua_State *L, TStatus errcode); | 95 | LUAI_FUNC l_noret luaD_throwbaselevel (lua_State *L, TStatus errcode); |
| @@ -1293,7 +1293,7 @@ static void finishgencycle (lua_State *L, global_State *g) { | |||
| 1293 | correctgraylists(g); | 1293 | correctgraylists(g); |
| 1294 | checkSizes(L, g); | 1294 | checkSizes(L, g); |
| 1295 | g->gcstate = GCSpropagate; /* skip restart */ | 1295 | g->gcstate = GCSpropagate; /* skip restart */ |
| 1296 | if (!g->gcemergency) | 1296 | if (!g->gcemergency && luaD_checkminstack(L)) |
| 1297 | callallpendingfinalizers(L); | 1297 | callallpendingfinalizers(L); |
| 1298 | } | 1298 | } |
| 1299 | 1299 | ||
| @@ -1667,12 +1667,13 @@ static l_mem singlestep (lua_State *L, int fast) { | |||
| 1667 | break; | 1667 | break; |
| 1668 | } | 1668 | } |
| 1669 | case GCScallfin: { /* call finalizers */ | 1669 | case GCScallfin: { /* call finalizers */ |
| 1670 | if (g->tobefnz && !g->gcemergency) { | 1670 | if (g->tobefnz && !g->gcemergency && luaD_checkminstack(L)) { |
| 1671 | g->gcstopem = 0; /* ok collections during finalizers */ | 1671 | g->gcstopem = 0; /* ok collections during finalizers */ |
| 1672 | GCTM(L); /* call one finalizer */ | 1672 | GCTM(L); /* call one finalizer */ |
| 1673 | stepresult = CWUFIN; | 1673 | stepresult = CWUFIN; |
| 1674 | } | 1674 | } |
| 1675 | else { /* emergency mode or no more finalizers */ | 1675 | else { /* no more finalizers or emergency mode or no enough stack |
| 1676 | to run finalizers */ | ||
| 1676 | g->gcstate = GCSpause; /* finish collection */ | 1677 | g->gcstate = GCSpause; /* finish collection */ |
| 1677 | stepresult = step2pause; | 1678 | stepresult = step2pause; |
| 1678 | } | 1679 | } |
