summaryrefslogtreecommitdiff
path: root/rts/RtsAPI.c
diff options
context:
space:
mode:
authorSimon Marlow <marlowsd@gmail.com>2008-11-19 12:48:48 +0000
committerSimon Marlow <marlowsd@gmail.com>2008-11-19 12:48:48 +0000
commit5cbe7adb6051a9d1738dfb5735c8c923b74c5945 (patch)
treee79827a16b6d43caf6057fd87be955d67d9ff764 /rts/RtsAPI.c
parent33189c6969f4838dab3558497dd66f7400ee77d0 (diff)
downloadhaskell-5cbe7adb6051a9d1738dfb5735c8c923b74c5945.tar.gz
Fix some more shutdown races
There were races between workerTaskStop() and freeTaskManager(): we need to be sure that all Tasks have exited properly before we start tearing things down. This isn't completely straighforward, see comments for details.
Diffstat (limited to 'rts/RtsAPI.c')
-rw-r--r--rts/RtsAPI.c18
1 files changed, 10 insertions, 8 deletions
diff --git a/rts/RtsAPI.c b/rts/RtsAPI.c
index 525ead25ac..d0bdead1c9 100644
--- a/rts/RtsAPI.c
+++ b/rts/RtsAPI.c
@@ -587,18 +587,20 @@ rts_unlock (Capability *cap)
task = cap->running_task;
ASSERT_FULL_CAPABILITY_INVARIANTS(cap,task);
- // slightly delicate ordering of operations below, pay attention!
-
- // We are no longer a bound task/thread. This is important,
- // because the GC can run when we release the Capability below,
- // and we don't want it to treat this as a live TSO pointer.
- task->tso = NULL;
-
// Now release the Capability. With the capability released, GC
// may happen. NB. does not try to put the current Task on the
// worker queue.
- releaseCapability(cap);
+ // NB. keep cap->lock held while we call boundTaskExiting(). This
+ // is necessary during shutdown, where we want the invariant that
+ // after shutdownCapability(), all the Tasks associated with the
+ // Capability have completed their shutdown too. Otherwise we
+ // could have boundTaskExiting()/workerTaskStop() running at some
+ // random point in the future, which causes problems for
+ // freeTaskManager().
+ ACQUIRE_LOCK(&cap->lock);
+ releaseCapability_(cap,rtsFalse);
// Finally, we can release the Task to the free list.
boundTaskExiting(task);
+ RELEASE_LOCK(&cap->lock);
}