[project @ 2004-09-28 15:08:58 by simonmar]
authorsimonmar <unknown>
Tue, 28 Sep 2004 15:08:58 +0000 (15:08 +0000)
committersimonmar <unknown>
Tue, 28 Sep 2004 15:08:58 +0000 (15:08 +0000)
rts_evalStableIO: set rtsApiCapability to NULL *before* calling
scheduleWaitThread, matching the way the other eval_* functions do
this.

The previous way lead to a suble race condition:
  - thread A calls rts_evalIO, enters scheduleWaitThread()
    (rtsApiCapability == NULL).
  - thread B calls rts_evalStableIO, creates a main thread and enters
    scheduleWaitThread() (rtsApiCapability == &MainCapability)
  - thread A exits scheduleWaitThread, sees that rtsApiCapability is
    non-NULL, and calls releaseCapability() on it.  This is bogus,
    because thread A doesn't actually hold the capability, and we've
    done a double-release.

This scenario leads to assertion failures in a debug threaded RTS, and
probably crashes in a non-debug threaded RTS.

MERGE TO STABLE

ghc/rts/RtsAPI.c

index 166778e..4ca1225 100644 (file)
@@ -430,11 +430,12 @@ rts_evalStableIO (HsStablePtr s, /*out*/HsStablePtr *ret)
     StgTSO* tso;
     StgClosure *p, *r;
     SchedulerStatus stat;
+    Capability *cap = rtsApiCapability;
+    rtsApiCapability = NULL;
     
     p = (StgClosure *)deRefStablePtr(s);
     tso = createStrictIOThread(RtsFlags.GcFlags.initialStkSize, p);
-    stat = scheduleWaitThread(tso,&r,rtsApiCapability);
-    rtsApiCapability = NULL;
+    stat = scheduleWaitThread(tso,&r,cap);
 
     if (stat == Success && ret != NULL) {
        ASSERT(r != NULL);