|
The first thing the gc pushes on the gray list (at the beginning of a cycle) is the main stack; consequently, it should be the last thing marked before atomic() is called; furthermore, stacks are marked atomically. However, it is *just* possible that singlestep calls propagatemark on the stack (at line 569) and then luaC_step decides to return before singlestep is called again. Just at that moment, a new object could be put on the stack, and would not be marked. I haven't managed to trigger this condition, though, other than with Mark Pall's example (and I haven't verified that this condition occurs in Mark's example either.) All the same, it seems that atomic should be called if g->gray is NULL *after* the call to propagatemark, rather than before it.
On 2-Aug-05, at 3:46 PM, Rici Lake wrote:
I believe the problem is in the function atomic() in lgc.c, at line 531:531 /* remark objects cautch by write barrier */ 532 propagateall(g); 533 /* remark occasional upvalues of (maybe) dead threads */ 534 remarkupvals(g); 535 /* remark weak tables */ 536 g->gray = g->weak; 537 g->weak = NULL;Line 534 marks open upvals, which effectively marks the object in the upval. However, the marks are not propagated, and then the gray list is wiped out at line 536. (The explanation for remarkupvals is in Roberto's very useful presentation on Lua's internals.)Moving the call to propagateall() at line 532 so that it comes after line 534 seems to solve the problem.