[project @ 2005-07-11 12:29:28 by simonmar]
authorsimonmar <unknown>
Mon, 11 Jul 2005 12:29:28 +0000 (12:29 +0000)
committersimonmar <unknown>
Mon, 11 Jul 2005 12:29:28 +0000 (12:29 +0000)
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.

ghc/rts/Exception.cmm
ghc/rts/Schedule.c

index 771af1f..23655f8 100644 (file)
    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,
index df1cace..ea791e5 100644 (file)
@@ -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);