summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorZubin Duggal <zubin@cmi.ac.in>2021-02-17 22:14:02 +0530
committerMarge Bot <ben+marge-bot@smart-cactus.org>2021-02-27 08:00:46 -0500
commitdf6d42d0c2534fe620798aab01a393dbd40573fb (patch)
treef7dca755ebd59b67082fd2c95220f50b9c0adf15
parent60bf4d7ca59e333db6349948b8140651d0190004 (diff)
downloadhaskell-df6d42d0c2534fe620798aab01a393dbd40573fb.tar.gz
Don't catch async exceptions when evaluating Template Haskell
-rw-r--r--compiler/GHC/Data/IOEnv.hs23
1 files changed, 20 insertions, 3 deletions
diff --git a/compiler/GHC/Data/IOEnv.hs b/compiler/GHC/Data/IOEnv.hs
index ab40687878..7d976b1f82 100644
--- a/compiler/GHC/Data/IOEnv.hs
+++ b/compiler/GHC/Data/IOEnv.hs
@@ -161,12 +161,29 @@ tryM (IOEnv thing) = IOEnv (\ env -> tryIOEnvFailure (thing env))
tryIOEnvFailure :: IO a -> IO (Either IOEnvFailure a)
tryIOEnvFailure = try
--- XXX We shouldn't be catching everything, e.g. timeouts
tryAllM :: IOEnv env r -> IOEnv env (Either SomeException r)
--- Catch *all* exceptions
+-- Catch *all* synchronous exceptions
-- This is used when running a Template-Haskell splice, when
-- even a pattern-match failure is a programmer error
-tryAllM (IOEnv thing) = IOEnv (\ env -> try (thing env))
+tryAllM (IOEnv thing) = IOEnv (\ env -> safeTry (thing env))
+
+-- | Like 'try', but doesn't catch asynchronous exceptions
+safeTry :: Exception e => IO a -> IO (Either e a)
+safeTry x = do
+ r <- try x
+ case r of
+ Left e
+ | isSyncException e -> pure $ Left e
+ | otherwise -> throwIO e
+ Right a -> pure $ pure a
+
+-- | Detect if a exception is synchronous
+-- Taken from safe-exceptions
+isSyncException :: Exception e => e -> Bool
+isSyncException e =
+ case fromException (toException e) of
+ Just (SomeAsyncException _) -> False
+ Nothing -> True
tryMostM :: IOEnv env r -> IOEnv env (Either SomeException r)
tryMostM (IOEnv thing) = IOEnv (\ env -> tryMost (thing env))