diff --git a/rts/Exception.cmm b/rts/Exception.cmm
index 24da1c690e50784451e5f144edce893029cb6f2c..591fa7ab9bc76bcdc75daffea6146a34f1f40486 100644
--- a/rts/Exception.cmm
+++ b/rts/Exception.cmm
@@ -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