From 117dc73b8a8f6a4184a825a96c372480377f4680 Mon Sep 17 00:00:00 2001 From: Simon Marlow Date: Thu, 20 Nov 2008 11:24:38 +0000 Subject: [PATCH] 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). --- rts/Schedule.c | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/rts/Schedule.c b/rts/Schedule.c index ed4d4b0..7dd0634 100644 --- a/rts/Schedule.c +++ b/rts/Schedule.c @@ -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++) { -- 1.7.10.4