Fix a rare deadlock when the IO manager thread is slow to start up
[ghc-hetmet.git] / rts / Capability.c
index bd781e9..cf85372 100644 (file)
@@ -394,7 +394,10 @@ releaseCapability_ (Capability* cap,
     // give this Capability to the appropriate Task.
     if (!emptyRunQueue(cap) && cap->run_queue_hd->bound) {
        // Make sure we're not about to try to wake ourselves up
-       ASSERT(task != cap->run_queue_hd->bound);
+       // ASSERT(task != cap->run_queue_hd->bound);
+        // assertion is false: in schedule() we force a yield after
+       // ThreadBlocked, but the thread may be back on the run queue
+       // by now.
        task = cap->run_queue_hd->bound;
        giveCapabilityToTask(cap,task);
        return;
@@ -783,10 +786,18 @@ shutdownCapability (Capability *cap, Task *task, rtsBool safe)
                       "thread(s) are involved in foreign calls, yielding");
             cap->running_task = NULL;
            RELEASE_LOCK(&cap->lock);
+            // The IO manager thread might have been slow to start up,
+            // so the first attempt to kill it might not have
+            // succeeded.  Just in case, try again - the kill message
+            // will only be sent once.
+            //
+            // To reproduce this deadlock: run ffi002(threaded1)
+            // repeatedly on a loaded machine.
+            ioManagerDie();
             yieldThread();
             continue;
         }
-            
+
         traceEventShutdown(cap);
        RELEASE_LOCK(&cap->lock);
        break;