summaryrefslogtreecommitdiff
path: root/rts/sm/MarkWeak.c
diff options
context:
space:
mode:
authorSimon Marlow <simonmar@microsoft.com>2007-04-04 10:30:27 +0000
committerSimon Marlow <simonmar@microsoft.com>2007-04-04 10:30:27 +0000
commitb01325cd38343133ac8f0a1d45e7b8d7cbb52a43 (patch)
tree3164130a7d196ff34b95cd2699f17e5922a8ed12 /rts/sm/MarkWeak.c
parentc8217b3d269ccbdcc6eb8a6e9a9e202d247ca7f4 (diff)
downloadhaskell-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.c19
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;