summaryrefslogtreecommitdiff
path: root/rts/Schedule.c
diff options
context:
space:
mode:
authorSimon Marlow <marlowsd@gmail.com>2008-11-13 16:00:05 +0000
committerSimon Marlow <marlowsd@gmail.com>2008-11-13 16:00:05 +0000
commitdddfba386d413d575c1d0be2a26f0cf1417fa5b6 (patch)
treebe516487fb461d3840de1fdddad4e59fd3e3c4f2 /rts/Schedule.c
parent6d31658583b97f84313cc7837a0eaeb4060022a7 (diff)
downloadhaskell-dddfba386d413d575c1d0be2a26f0cf1417fa5b6.tar.gz
Fix another subtle shutdown deadlock
The problem occurred when a thread tries to GC during shutdown. In order to GC it has to acquire all the Capabilities in the system, but during shutdown, some of the Capabilities have already been closed and can never be acquired.
Diffstat (limited to 'rts/Schedule.c')
-rw-r--r--rts/Schedule.c16
1 files changed, 15 insertions, 1 deletions
diff --git a/rts/Schedule.c b/rts/Schedule.c
index 499cf77e9b..aedd6b7d80 100644
--- a/rts/Schedule.c
+++ b/rts/Schedule.c
@@ -340,7 +340,14 @@ schedule (Capability *initialCapability, Task *task)
#endif
/* scheduleDoGC() deletes all the threads */
cap = scheduleDoGC(cap,task,rtsFalse);
- break;
+
+ // after scheduleDoGC(), we must be shutting down. Either some
+ // other Capability did the final GC, or we did it above,
+ // either way we can fall through to the SCHED_SHUTTING_DOWN
+ // case now.
+ ASSERT(sched_state == SCHED_SHUTTING_DOWN);
+ // fall through
+
case SCHED_SHUTTING_DOWN:
debugTrace(DEBUG_sched, "SCHED_SHUTTING_DOWN");
// If we are a worker, just exit. If we're a bound thread
@@ -1467,6 +1474,13 @@ scheduleDoGC (Capability *cap, Task *task USED_IF_THREADS, rtsBool force_major)
nat i;
#endif
+ if (sched_state == SCHED_SHUTTING_DOWN) {
+ // The final GC has already been done, and the system is
+ // shutting down. We'll probably deadlock if we try to GC
+ // now.
+ return cap;
+ }
+
#ifdef THREADED_RTS
// In order to GC, there must be no threads running Haskell code.
// Therefore, the GC thread needs to hold *all* the capabilities,