Commit 117dc73b authored by Simon Marlow's avatar Simon Marlow

Fix a race in the deadlock-detection code

After a deadlock it was possible for the timer signal to remain off,
which meant that the next deadlock would not be detected, and the
system would hang.  Spotted by conc047(threaded2).
parent 01014815
......@@ -1001,12 +1001,11 @@ scheduleDetectDeadlock (Capability *cap, Task *task)
// they are unreachable and will therefore be sent an
// exception. Any threads thus released will be immediately
// runnable.
cap = scheduleDoGC (cap, task, rtsTrue/*force major GC*/);
cap = scheduleDoGC (cap, task, rtsTrue/*force major GC*/);
// when force_major == rtsTrue. scheduleDoGC sets
// recent_activity to ACTIVITY_DONE_GC and turns off the timer
// signal.
recent_activity = ACTIVITY_DONE_GC;
// disable timer signals (see #1623)
stopTimer();
if ( !emptyRunQueue(cap) ) return;
#if defined(RTS_USER_SIGNALS) && !defined(THREADED_RTS)
......@@ -1577,6 +1576,16 @@ scheduleDoGC (Capability *cap, Task *task USED_IF_THREADS, rtsBool force_major)
balanceSparkPoolsCaps(n_capabilities, capabilities);
#endif
if (force_major)
{
// We've just done a major GC and we don't need the timer
// signal turned on any more (#1623).
// NB. do this *before* releasing the Capabilities, to avoid
// deadlocks!
recent_activity = ACTIVITY_DONE_GC;
stopTimer();
}
#if defined(THREADED_RTS)
// release our stash of capabilities.
for (i = 0; i < n_capabilities; i++) {
......
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