From: simonmar Date: Mon, 11 Jul 2005 12:29:28 +0000 (+0000) Subject: [project @ 2005-07-11 12:29:28 by simonmar] X-Git-Tag: Initial_conversion_from_CVS_complete~380 X-Git-Url: http://git.megacz.com/?a=commitdiff_plain;h=b8105b2b5e5b38c8ce4dca8979f5057c3159cfa0;p=ghc-hetmet.git [project @ 2005-07-11 12:29:28 by simonmar] awakenBlockedQueue(): check for NULL. This is a hack to workaround a bug that occurs when async exceptions, unsafePerformIO, and interruptible operations are used together. See the comment in Exceptions.cmm and bug #1235728 for more details. --- diff --git a/ghc/rts/Exception.cmm b/ghc/rts/Exception.cmm index 771af1f..23655f8 100644 --- a/ghc/rts/Exception.cmm +++ b/ghc/rts/Exception.cmm @@ -35,6 +35,18 @@ it. The action of unblocking exceptions in a thread will release all the threads waiting to deliver exceptions to that thread. + NB. there's a bug in here. If a thread is inside an + unsafePerformIO, and inside blockAsyncExceptions# (there is an + unblockAsyncExceptions_ret on the stack), and it is blocked in an + interruptible operation, and it receives an exception, then the + unsafePerformIO thunk will be updated with a stack object + containing the unblockAsyncExceptions_ret frame. Later, when + someone else evaluates this thunk, the blocked exception state is + not restored, and the result is that unblockAsyncExceptions_ret + will attempt to unblock exceptions in the current thread, but it'll + find that the CurrentTSO->blocked_exceptions is NULL. Hence, we + work around this by checking for NULL in awakenBlockedQueue(). + -------------------------------------------------------------------------- */ INFO_TABLE_RET( stg_unblockAsyncExceptionszh_ret, diff --git a/ghc/rts/Schedule.c b/ghc/rts/Schedule.c index df1cace..ea791e5 100644 --- a/ghc/rts/Schedule.c +++ b/ghc/rts/Schedule.c @@ -3232,6 +3232,8 @@ awakenBlockedQueue(StgBlockingQueueElement *q, StgClosure *node) void awakenBlockedQueueNoLock(StgTSO *tso) { + if (tso == NULL) return; // hack; see bug #1235728, and comments in + // Exception.cmm while (tso != END_TSO_QUEUE) { tso = unblockOneLocked(tso); } @@ -3240,6 +3242,8 @@ awakenBlockedQueueNoLock(StgTSO *tso) void awakenBlockedQueue(StgTSO *tso) { + if (tso == NULL) return; // hack; see bug #1235728, and comments in + // Exception.cmm ACQUIRE_LOCK(&sched_mutex); while (tso != END_TSO_QUEUE) { tso = unblockOneLocked(tso);