Commit 07291441 authored by simonmar's avatar simonmar
Browse files

[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
parent c6226d8a
...@@ -430,11 +430,12 @@ rts_evalStableIO (HsStablePtr s, /*out*/HsStablePtr *ret) ...@@ -430,11 +430,12 @@ rts_evalStableIO (HsStablePtr s, /*out*/HsStablePtr *ret)
StgTSO* tso; StgTSO* tso;
StgClosure *p, *r; StgClosure *p, *r;
SchedulerStatus stat; SchedulerStatus stat;
Capability *cap = rtsApiCapability;
rtsApiCapability = NULL;
p = (StgClosure *)deRefStablePtr(s); p = (StgClosure *)deRefStablePtr(s);
tso = createStrictIOThread(RtsFlags.GcFlags.initialStkSize, p); tso = createStrictIOThread(RtsFlags.GcFlags.initialStkSize, p);
stat = scheduleWaitThread(tso,&r,rtsApiCapability); stat = scheduleWaitThread(tso,&r,cap);
rtsApiCapability = NULL;
if (stat == Success && ret != NULL) { if (stat == Success && ret != NULL) {
ASSERT(r != NULL); ASSERT(r != NULL);
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment