@@ -93,7 +93,7 @@ import Control.Exception (Exception (..), SomeException (..), SomeAsyncException
93
93
import qualified Control.Exception as E
94
94
import qualified Control.Monad.Catch as C
95
95
import Control.Monad.Catch (Handler (.. ))
96
- import Control.Monad (liftM )
96
+ import Control.Monad (liftM , void )
97
97
import Control.Monad.IO.Class (MonadIO , liftIO )
98
98
import Data.Typeable (Typeable , cast )
99
99
@@ -366,13 +366,12 @@ onException thing after = withException thing (\(_ :: SomeException) -> after)
366
366
-- @since 0.1.0.0
367
367
withException :: (C. MonadMask m , E. Exception e ) => m a -> (e -> m b ) -> m a
368
368
withException thing after = C. uninterruptibleMask $ \ restore -> do
369
- res1 <- C. try $ restore thing
370
- case res1 of
371
- Left e1 -> do
372
- -- see explanation in bracket
373
- _ :: Either SomeException b <- C. try $ after e1
374
- C. throwM e1
375
- Right x -> return x
369
+ fmap fst $ C. generalBracket (pure () ) cAfter (const $ restore thing)
370
+ where
371
+ -- ignore the exception from after, see bracket for explanation
372
+ cAfter () (C. ExitCaseException se) | Just ex <- fromException se =
373
+ ignoreExceptions $ after ex
374
+ cAfter () _ = pure ()
376
375
377
376
-- | Async safe version of 'E.bracket'
378
377
--
@@ -392,31 +391,25 @@ bracket_ before after thing = bracket before (const after) (const thing)
392
391
-- @since 0.1.0.0
393
392
finally :: C. MonadMask m => m a -> m b -> m a
394
393
finally thing after = C. uninterruptibleMask $ \ restore -> do
395
- res1 <- C. try $ restore thing
396
- case res1 of
397
- Left (e1 :: SomeException ) -> do
398
- -- see bracket for explanation
399
- _ :: Either SomeException b <- C. try after
400
- C. throwM e1
401
- Right x -> do
402
- _ <- after
403
- return x
394
+ fmap fst $ C. generalBracket (pure () ) cAfter (const $ restore thing)
395
+ where
396
+ -- ignore the exception from after, see bracket for explanation
397
+ cAfter () (C. ExitCaseException se) =
398
+ ignoreExceptions after
399
+ cAfter () _ = void after
404
400
405
401
-- | Async safe version of 'E.bracketOnError'
406
402
--
407
403
-- @since 0.1.0.0
408
404
bracketOnError :: forall m a b c . C. MonadMask m
409
405
=> m a -> (a -> m b ) -> (a -> m c ) -> m c
410
- bracketOnError before after thing = C. mask $ \ restore -> do
411
- x <- before
412
- res1 <- C. try $ restore (thing x)
413
- case res1 of
414
- Left (e1 :: SomeException ) -> do
415
- -- ignore the exception, see bracket for explanation
416
- _ :: Either SomeException b <-
417
- C. try $ C. uninterruptibleMask_ $ after x
418
- C. throwM e1
419
- Right y -> return y
406
+ bracketOnError before after thing = fmap fst $ C. generalBracket before cAfter thing
407
+ where
408
+ -- ignore the exception from after, see bracket for explanation
409
+ cAfter x (C. ExitCaseException se) =
410
+ C. uninterruptibleMask_ $ ignoreExceptions $ after x
411
+ cAfter x _ = pure ()
412
+
420
413
421
414
-- | A variant of 'bracketOnError' where the return value from the first
422
415
-- computation is not required.
@@ -431,22 +424,21 @@ bracketOnError_ before after thing = bracketOnError before (const after) (const
431
424
-- @since 0.1.7.0
432
425
bracketWithError :: forall m a b c . C. MonadMask m
433
426
=> m a -> (Maybe SomeException -> a -> m b ) -> (a -> m c ) -> m c
434
- bracketWithError before after thing = C. mask $ \ restore -> do
435
- x <- before
436
- res1 <- C. try $ restore (thing x)
437
- case res1 of
438
- Left (e1 :: SomeException ) -> do
439
- -- explicitly ignore exceptions from after. We know that
440
- -- no async exceptions were thrown there, so therefore
441
- -- the stronger exception must come from thing
442
- --
443
- -- https://github.com/fpco/safe-exceptions/issues/2
444
- _ :: Either SomeException b <-
445
- C. try $ C. uninterruptibleMask_ $ after (Just e1) x
446
- C. throwM e1
447
- Right y -> do
448
- _ <- C. uninterruptibleMask_ $ after Nothing x
449
- return y
427
+ bracketWithError before after thing = fmap fst $ C. generalBracket before cAfter thing
428
+ where
429
+ cAfter x (C. ExitCaseException se) =
430
+ C. uninterruptibleMask_ $ ignoreExceptions $ after (Just se) x
431
+ cAfter x _ =
432
+ void $ C. uninterruptibleMask_ $ after Nothing x
433
+
434
+ -- | Internal function that swallows all exceptions, used in some bracket-like
435
+ -- combinators. When it's run inside of uninterruptibleMask, we know that
436
+ -- no async exceptions can be thrown from thing, so the other exception from
437
+ -- the combinator will not be overridden.
438
+ --
439
+ -- https://github.com/fpco/safe-exceptions/issues/2
440
+ ignoreExceptions :: C. MonadMask m => m a -> m ()
441
+ ignoreExceptions thing = void thing `C.catch` (\ (_ :: SomeException ) -> pure () )
450
442
451
443
-- | Wrap up an asynchronous exception to be treated as a synchronous
452
444
-- exception
0 commit comments