diff options
author | Simon Marlow <simonmar@microsoft.com> | 2007-04-04 10:30:27 +0000 |
---|---|---|
committer | Simon Marlow <simonmar@microsoft.com> | 2007-04-04 10:30:27 +0000 |
commit | b01325cd38343133ac8f0a1d45e7b8d7cbb52a43 (patch) | |
tree | 3164130a7d196ff34b95cd2699f17e5922a8ed12 /rts/sm/MarkWeak.c | |
parent | c8217b3d269ccbdcc6eb8a6e9a9e202d247ca7f4 (diff) | |
download | haskell-b01325cd38343133ac8f0a1d45e7b8d7cbb52a43.tar.gz |
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 <<loop>>s in concurrent programs, so
it's a good one to fix.
Diffstat (limited to 'rts/sm/MarkWeak.c')
-rw-r--r-- | rts/sm/MarkWeak.c | 19 |
1 files changed, 14 insertions, 5 deletions
diff --git a/rts/sm/MarkWeak.c b/rts/sm/MarkWeak.c index 49134da826..455b586289 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; |