Fix #4988: we were wrongly running exception handlers in the
authorSimon Marlow <marlowsd@gmail.com>
Wed, 31 Aug 2011 21:45:01 +0000 (22:45 +0100)
committerSimon Marlow <marlowsd@gmail.com>
Thu, 1 Sep 2011 10:14:38 +0000 (11:14 +0100)
maskUninterruptible state instead of ordinary mask, due to a
misinterpretation of the way the TSO_INTERRUPTIBLE flag works.

Remarkably this must have been broken for quite some time.  Indeed we
even had a test that demonstrated the wrong behaviour (conc015a) but
presumably I didn't look hard enough at the output to notice that it
was wrong.

rts/Exception.cmm

index 24da1c6..591fa7a 100644 (file)
@@ -556,17 +556,19 @@ retry_pop_stack:
     }
 
     /* Ensure that async excpetions are blocked when running the handler.
-     * The interruptible state is inherited from the context of the
-     * catch frame.
     */
     StgTSO_flags(CurrentTSO) = %lobits32(
-       TO_W_(StgTSO_flags(CurrentTSO)) | TSO_BLOCKEX);
-    if ((StgCatchFrame_exceptions_blocked(frame) & TSO_INTERRUPTIBLE) == 0) {
+        TO_W_(StgTSO_flags(CurrentTSO)) | TSO_BLOCKEX | TSO_INTERRUPTIBLE);
+
+    /* The interruptible state is inherited from the context of the
+     * catch frame, but note that TSO_INTERRUPTIBLE is only meaningful
+     * if TSO_BLOCKEX is set.  (we got this wrong earlier, and #4988
+     * was a symptom of the bug).
+     */
+    if ((StgCatchFrame_exceptions_blocked(frame) &
+         (TSO_BLOCKEX | TSO_INTERRUPTIBLE)) == TSO_BLOCKEX) {
         StgTSO_flags(CurrentTSO) = %lobits32(
             TO_W_(StgTSO_flags(CurrentTSO)) & ~TSO_INTERRUPTIBLE);
-    } else {
-        StgTSO_flags(CurrentTSO) = %lobits32(
-            TO_W_(StgTSO_flags(CurrentTSO)) | TSO_INTERRUPTIBLE);
     }
 
     /* Call the handler, passing the exception value and a realworld