diff options
author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2008-06-23 19:07:44 -0300 |
---|---|---|
committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2008-06-23 19:07:44 -0300 |
commit | c3525610fea8554e6ee4cb9bdd144d25764ddfad (patch) | |
tree | 5bafab732fff4b7b8d5ccb08857907e8ee842b96 /lgc.c | |
parent | 7ba62e29856458469ae42a7be83856a0ec81e539 (diff) | |
download | lua-c3525610fea8554e6ee4cb9bdd144d25764ddfad.tar.gz lua-c3525610fea8554e6ee4cb9bdd144d25764ddfad.tar.bz2 lua-c3525610fea8554e6ee4cb9bdd144d25764ddfad.zip |
bug: when closing the state, 'luaC_separateudata' might mark
userdata in the wrong phase of collection, therefore avoiding
their traversal
Diffstat (limited to 'lgc.c')
-rw-r--r-- | lgc.c | 8 |
1 files changed, 3 insertions, 5 deletions
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lgc.c,v 2.44 2008/02/19 18:55:09 roberto Exp roberto $ | 2 | ** $Id: lgc.c,v 2.45 2008/06/23 16:51:28 roberto Exp roberto $ |
3 | ** Garbage Collector | 3 | ** Garbage Collector |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -210,7 +210,6 @@ static void markbeingfnz (global_State *g) { | |||
210 | do { | 210 | do { |
211 | u = gch(u)->next; | 211 | u = gch(u)->next; |
212 | lua_assert(testbit(gch(u)->marked, SEPARATED)); | 212 | lua_assert(testbit(gch(u)->marked, SEPARATED)); |
213 | lua_assert(!iswhite(u)); /* must be marked, if left from previous GC */ | ||
214 | makewhite(g, u); | 213 | makewhite(g, u); |
215 | reallymarkobject(g, u); | 214 | reallymarkobject(g, u); |
216 | } while (u != g->tobefnz); | 215 | } while (u != g->tobefnz); |
@@ -664,12 +663,10 @@ size_t luaC_separateudata (lua_State *L, int all) { | |||
664 | while ((curr = *p) != NULL) { | 663 | while ((curr = *p) != NULL) { |
665 | lua_assert(ttisuserdata(gch(curr)) && !isfinalized(gco2u(curr))); | 664 | lua_assert(ttisuserdata(gch(curr)) && !isfinalized(gco2u(curr))); |
666 | lua_assert(testbit(gch(curr)->marked, SEPARATED)); | 665 | lua_assert(testbit(gch(curr)->marked, SEPARATED)); |
667 | if (all) makewhite(g, curr); /* if 'all', collect all objects */ | 666 | if (!(all || iswhite(curr))) /* not being collected? */ |
668 | if (!iswhite(curr)) /* not being collected? */ | ||
669 | p = &gch(curr)->next; /* don't bother with it */ | 667 | p = &gch(curr)->next; /* don't bother with it */ |
670 | else { | 668 | else { |
671 | l_setbit(gch(curr)->marked, FINALIZEDBIT); /* won't be finalized again */ | 669 | l_setbit(gch(curr)->marked, FINALIZEDBIT); /* won't be finalized again */ |
672 | reallymarkobject(g, curr); /* won't be collected now */ | ||
673 | deadmem += sizeudata(gco2u(curr)); | 670 | deadmem += sizeudata(gco2u(curr)); |
674 | *p = gch(curr)->next; /* remove 'curr' from 'tmudata' list */ | 671 | *p = gch(curr)->next; /* remove 'curr' from 'tmudata' list */ |
675 | /* link 'curr' at the end of 'tobefnz' list */ | 672 | /* link 'curr' at the end of 'tobefnz' list */ |
@@ -746,6 +743,7 @@ static void atomic (lua_State *L) { | |||
746 | traverselistofgrays(g, &g->grayagain); /* remark gray again */ | 743 | traverselistofgrays(g, &g->grayagain); /* remark gray again */ |
747 | convergeephemerons(g); | 744 | convergeephemerons(g); |
748 | udsize = luaC_separateudata(L, 0); /* separate userdata to be finalized */ | 745 | udsize = luaC_separateudata(L, 0); /* separate userdata to be finalized */ |
746 | markbeingfnz(g); /* mark userdata that will be finalized */ | ||
749 | udsize += propagateall(g); /* remark, to propagate `preserveness' */ | 747 | udsize += propagateall(g); /* remark, to propagate `preserveness' */ |
750 | convergeephemerons(g); | 748 | convergeephemerons(g); |
751 | /* remove collected objects from weak tables */ | 749 | /* remove collected objects from weak tables */ |