diff options
author | Simon Marlow <marlowsd@gmail.com> | 2008-11-19 12:48:48 +0000 |
---|---|---|
committer | Simon Marlow <marlowsd@gmail.com> | 2008-11-19 12:48:48 +0000 |
commit | 5cbe7adb6051a9d1738dfb5735c8c923b74c5945 (patch) | |
tree | e79827a16b6d43caf6057fd87be955d67d9ff764 /rts/RtsAPI.c | |
parent | 33189c6969f4838dab3558497dd66f7400ee77d0 (diff) | |
download | haskell-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.c | 18 |
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); } |