Skip to content

Commit 91c00c5

Browse files
committed
rethrow
feat: support for exception context propagation We specialize the `throwIO` call using a newly implemented `rethrowIO'` which behaves as `rethrowIO` from base 4.21 when available or like the previous `throw` implementation. In short: - Before `base-4.21`, the code is exactly as before - After `base-4.21`, the code does not override the backtrace annotations and instead uses `rethrowIO`. Example of usage / changes: The following code: ```haskell {-# LANGUAGE DeriveAnyClass #-} import Control.Concurrent.Async import Control.Exception import Control.Exception.Context import Control.Exception.Annotation import Data.Typeable import Data.Traversable import GHC.Stack data Ann = Ann String deriving (Show, ExceptionAnnotation) asyncTask :: HasCallStack => IO () asyncTask = annotateIO (Ann "bonjour") $ do error "yoto" asyncTask' :: HasCallStack => IO () asyncTask' = annotateIO (Ann "bonjour2") $ do error "yutu" main = do -- withAsync asyncTask wait concurrently asyncTask asyncTask' -- race asyncTask asyncTask' ``` When run without this commit leads to: ``` ASyncException.hs: Uncaught exception ghc-internal:GHC.Internal.Exception.ErrorCall: yoto HasCallStack backtrace: throwIO, called at ./Control/Concurrent/Async/Internal.hs:630:24 in async-2.2.5-50rpfAJ7BEc1o5OswtTMUN:Control.Concurrent.Async.Internal ``` When run with this commit: ``` *** Exception: yoto Ann "bonjour" HasCallStack backtrace: error, called at /home/guillaume//ASyncException.hs:15:3 in async-2.2.5-inplace:Main asyncTask, called at /home/guillaume//ASyncException.hs:23:16 in async-2.2.5-inplace:Main ```
1 parent 7ac0e51 commit 91c00c5

File tree

1 file changed

+19
-5
lines changed

1 file changed

+19
-5
lines changed

Control/Concurrent/Async/Internal.hs

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
{-# LANGUAGE DeriveDataTypeable #-}
88
#endif
99
{-# OPTIONS -Wall #-}
10+
{-# LANGUAGE ScopedTypeVariables #-}
1011

1112
-----------------------------------------------------------------------------
1213
-- |
@@ -182,10 +183,23 @@ withAsyncUsing doFork = \action inner -> do
182183
let a = Async t (readTMVar var)
183184
r <- restore (inner a) `catchAll` \e -> do
184185
uninterruptibleCancel a
185-
throwIO e
186+
rethrowIO' e
186187
uninterruptibleCancel a
187188
return r
188189

190+
191+
-- | This function attempts at rethrowing while keeping the context
192+
-- This is internal and only working with GHC >=9.12
193+
rethrowIO' :: SomeException -> IO a
194+
#if MIN_VERSION_base(4,21,0)
195+
rethrowIO' e =
196+
case fromException e of
197+
Just (e' :: ExceptionWithContext SomeException) -> rethrowIO e'
198+
Nothing -> throwIO e
199+
#else
200+
rethrowIO' = throwIO
201+
#endif
202+
189203
-- | Wait for an asynchronous action to complete, and return its
190204
-- value. If the asynchronous action threw an exception, then the
191205
-- exception is re-thrown by 'wait'.
@@ -613,7 +627,7 @@ race left right = concurrently' left right collect
613627
collect m = do
614628
e <- m
615629
case e of
616-
Left ex -> throwIO ex
630+
Left ex -> rethrowIO' ex
617631
Right r -> return r
618632

619633
-- race_ :: IO a -> IO b -> IO ()
@@ -627,7 +641,7 @@ concurrently left right = concurrently' left right (collect [])
627641
collect xs m = do
628642
e <- m
629643
case e of
630-
Left ex -> throwIO ex
644+
Left ex -> rethrowIO' ex
631645
Right r -> collect (r:xs) m
632646

633647
-- concurrentlyE :: IO (Either e a) -> IO (Either e b) -> IO (Either e (a, b))
@@ -640,7 +654,7 @@ concurrentlyE left right = concurrently' left right (collect [])
640654
collect xs m = do
641655
e <- m
642656
case e of
643-
Left ex -> throwIO ex
657+
Left ex -> rethrowIO' ex
644658
Right r -> collect (r:xs) m
645659

646660
concurrently' :: IO a -> IO b
@@ -699,7 +713,7 @@ concurrently_ left right = concurrently' left right (collect 0)
699713
collect i m = do
700714
e <- m
701715
case e of
702-
Left ex -> throwIO ex
716+
Left ex -> rethrowIO' ex
703717
Right _ -> collect (i + 1 :: Int) m
704718

705719

0 commit comments

Comments
 (0)