From: simonmar Date: Tue, 28 Sep 2004 15:08:58 +0000 (+0000) Subject: [project @ 2004-09-28 15:08:58 by simonmar] X-Git-Tag: Initial_conversion_from_CVS_complete~1570 X-Git-Url: http://git.megacz.com/?a=commitdiff_plain;h=07291441614c93357b813f7d4d007e9c32636582;p=ghc-hetmet.git [project @ 2004-09-28 15:08:58 by simonmar] 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 --- diff --git a/ghc/rts/RtsAPI.c b/ghc/rts/RtsAPI.c index 166778e..4ca1225 100644 --- a/ghc/rts/RtsAPI.c +++ b/ghc/rts/RtsAPI.c @@ -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);