From: Simon Marlow Date: Wed, 4 Apr 2007 10:30:27 +0000 (+0000) Subject: MERGE: Fix bug exposed by conc052. X-Git-Url: http://git.megacz.com/?p=ghc-hetmet.git;a=commitdiff_plain;h=b01325cd38343133ac8f0a1d45e7b8d7cbb52a43 MERGE: Fix bug exposed by conc052. A thread that was blocked on a blackhole but can now be woken up could possibly be treated as unreachable by the GC, and sent the NonTermination exception. This can give rise to spurious <>s in concurrent programs, so it's a good one to fix. --- diff --git a/rts/sm/MarkWeak.c b/rts/sm/MarkWeak.c index 49134da..455b586 100644 --- a/rts/sm/MarkWeak.c +++ b/rts/sm/MarkWeak.c @@ -284,17 +284,26 @@ traverseBlackholeQueue (void) { StgTSO *prev, *t, *tmp; rtsBool flag; + nat type; flag = rtsFalse; prev = NULL; for (t = blackhole_queue; t != END_TSO_QUEUE; prev=t, t = t->link) { + // if the thread is not yet alive... if (! (tmp = (StgTSO *)isAlive((StgClosure*)t))) { - if (isAlive(t->block_info.closure)) { - t = (StgTSO *)evacuate((StgClosure *)t); - if (prev) prev->link = t; - flag = rtsTrue; - } + // if the closure it is blocked on is either (a) a + // reachable BLAKCHOLE or (b) not a BLACKHOLE, then we + // make the thread alive. + if (!isAlive(t->block_info.closure)) { + type = get_itbl(t->block_info.closure)->type; + if (type == BLACKHOLE || type == CAF_BLACKHOLE) { + continue; + } + } + t = (StgTSO *)evacuate((StgClosure *)t); + if (prev) prev->link = t; + flag = rtsTrue; } } return flag;