diff options
| -rw-r--r-- | lgc.c | 10 | ||||
| -rw-r--r-- | lgc.h | 1 | ||||
| -rw-r--r-- | testes/main.lua | 28 |
3 files changed, 34 insertions, 5 deletions
| @@ -907,7 +907,7 @@ static void GCTM (lua_State *L) { | |||
| 907 | int status; | 907 | int status; |
| 908 | lu_byte oldah = L->allowhook; | 908 | lu_byte oldah = L->allowhook; |
| 909 | int oldgcstp = g->gcstp; | 909 | int oldgcstp = g->gcstp; |
| 910 | g->gcstp = GCSTPGC; /* avoid GC steps */ | 910 | g->gcstp |= GCSTPGC; /* avoid GC steps */ |
| 911 | L->allowhook = 0; /* stop debug hooks during GC metamethod */ | 911 | L->allowhook = 0; /* stop debug hooks during GC metamethod */ |
| 912 | setobj2s(L, L->top++, tm); /* push finalizer... */ | 912 | setobj2s(L, L->top++, tm); /* push finalizer... */ |
| 913 | setobj2s(L, L->top++, &v); /* ... and its argument */ | 913 | setobj2s(L, L->top++, &v); /* ... and its argument */ |
| @@ -1011,7 +1011,8 @@ static void correctpointers (global_State *g, GCObject *o) { | |||
| 1011 | void luaC_checkfinalizer (lua_State *L, GCObject *o, Table *mt) { | 1011 | void luaC_checkfinalizer (lua_State *L, GCObject *o, Table *mt) { |
| 1012 | global_State *g = G(L); | 1012 | global_State *g = G(L); |
| 1013 | if (tofinalize(o) || /* obj. is already marked... */ | 1013 | if (tofinalize(o) || /* obj. is already marked... */ |
| 1014 | gfasttm(g, mt, TM_GC) == NULL) /* or has no finalizer? */ | 1014 | gfasttm(g, mt, TM_GC) == NULL || /* or has no finalizer... */ |
| 1015 | (g->gcstp & GCSTPCLS)) /* or closing state? */ | ||
| 1015 | return; /* nothing to be done */ | 1016 | return; /* nothing to be done */ |
| 1016 | else { /* move 'o' to 'finobj' list */ | 1017 | else { /* move 'o' to 'finobj' list */ |
| 1017 | GCObject **p; | 1018 | GCObject **p; |
| @@ -1502,14 +1503,13 @@ static void deletelist (lua_State *L, GCObject *p, GCObject *limit) { | |||
| 1502 | */ | 1503 | */ |
| 1503 | void luaC_freeallobjects (lua_State *L) { | 1504 | void luaC_freeallobjects (lua_State *L) { |
| 1504 | global_State *g = G(L); | 1505 | global_State *g = G(L); |
| 1505 | g->gcstp = GCSTPGC; | 1506 | g->gcstp = GCSTPCLS; /* no extra finalizers after here */ |
| 1506 | luaC_changemode(L, KGC_INC); | 1507 | luaC_changemode(L, KGC_INC); |
| 1507 | separatetobefnz(g, 1); /* separate all objects with finalizers */ | 1508 | separatetobefnz(g, 1); /* separate all objects with finalizers */ |
| 1508 | lua_assert(g->finobj == NULL); | 1509 | lua_assert(g->finobj == NULL); |
| 1509 | g->gcstp = 0; | ||
| 1510 | callallpendingfinalizers(L); | 1510 | callallpendingfinalizers(L); |
| 1511 | deletelist(L, g->allgc, obj2gco(g->mainthread)); | 1511 | deletelist(L, g->allgc, obj2gco(g->mainthread)); |
| 1512 | deletelist(L, g->finobj, NULL); | 1512 | lua_assert(g->finobj == NULL); /* no new finalizers */ |
| 1513 | deletelist(L, g->fixedgc, NULL); /* collect fixed objects */ | 1513 | deletelist(L, g->fixedgc, NULL); /* collect fixed objects */ |
| 1514 | lua_assert(g->strt.nuse == 0); | 1514 | lua_assert(g->strt.nuse == 0); |
| 1515 | } | 1515 | } |
| @@ -154,6 +154,7 @@ | |||
| 154 | */ | 154 | */ |
| 155 | #define GCSTPUSR 1 /* bit true when GC stopped by user */ | 155 | #define GCSTPUSR 1 /* bit true when GC stopped by user */ |
| 156 | #define GCSTPGC 2 /* bit true when GC stopped by itself */ | 156 | #define GCSTPGC 2 /* bit true when GC stopped by itself */ |
| 157 | #define GCSTPCLS 4 /* bit true when closing Lua state */ | ||
| 157 | #define gcrunning(g) ((g)->gcstp == 0) | 158 | #define gcrunning(g) ((g)->gcstp == 0) |
| 158 | 159 | ||
| 159 | 160 | ||
diff --git a/testes/main.lua b/testes/main.lua index 52c77954..9def6386 100644 --- a/testes/main.lua +++ b/testes/main.lua | |||
| @@ -261,6 +261,34 @@ u2 = setmetatable({}, {__gc = function () error("ZYX") end}) | |||
| 261 | RUN('lua -W %s 2> %s', prog, out) | 261 | RUN('lua -W %s 2> %s', prog, out) |
| 262 | checkprogout("ZYX)\nXYZ)\n") | 262 | checkprogout("ZYX)\nXYZ)\n") |
| 263 | 263 | ||
| 264 | -- bug since 5.2: finalizer called when closing a state could | ||
| 265 | -- subvert finalization order | ||
| 266 | prepfile[[ | ||
| 267 | -- should be called last | ||
| 268 | print("creating 1") | ||
| 269 | setmetatable({}, {__gc = function () print(1) end}) | ||
| 270 | |||
| 271 | print("creating 2") | ||
| 272 | setmetatable({}, {__gc = function () | ||
| 273 | print("2") | ||
| 274 | print("creating 3") | ||
| 275 | -- this finalizer should not be called, as object will be | ||
| 276 | -- created after 'lua_close' has been called | ||
| 277 | setmetatable({}, {__gc = function () print(3) end}) | ||
| 278 | print(collectgarbage()) -- cannot call collector here | ||
| 279 | os.exit(0, true) | ||
| 280 | end}) | ||
| 281 | ]] | ||
| 282 | RUN('lua -W %s > %s', prog, out) | ||
| 283 | checkout[[ | ||
| 284 | creating 1 | ||
| 285 | creating 2 | ||
| 286 | 2 | ||
| 287 | creating 3 | ||
| 288 | nil | ||
| 289 | 1 | ||
| 290 | ]] | ||
| 291 | |||
| 264 | 292 | ||
| 265 | -- test many arguments | 293 | -- test many arguments |
| 266 | prepfile[[print(({...})[30])]] | 294 | prepfile[[print(({...})[30])]] |
