diff options
author | Zubin Duggal <zubin@cmi.ac.in> | 2021-02-17 22:14:02 +0530 |
---|---|---|
committer | Marge Bot <ben+marge-bot@smart-cactus.org> | 2021-02-27 08:00:46 -0500 |
commit | df6d42d0c2534fe620798aab01a393dbd40573fb (patch) | |
tree | f7dca755ebd59b67082fd2c95220f50b9c0adf15 /compiler/GHC/Data | |
parent | 60bf4d7ca59e333db6349948b8140651d0190004 (diff) | |
download | haskell-df6d42d0c2534fe620798aab01a393dbd40573fb.tar.gz |
Don't catch async exceptions when evaluating Template Haskell
Diffstat (limited to 'compiler/GHC/Data')
-rw-r--r-- | compiler/GHC/Data/IOEnv.hs | 23 |
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)) |