From 07291441614c93357b813f7d4d007e9c32636582 Mon Sep 17 00:00:00 2001 From: simonmar Date: Tue, 28 Sep 2004 15:08:58 +0000 Subject: [PATCH] [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 --- ghc/rts/RtsAPI.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) 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); -- 1.7.10.4