Skip to content

Commit

Permalink
Don't catch async exceptions
Browse files Browse the repository at this point in the history
  • Loading branch information
hasufell committed Nov 15, 2024
1 parent 9b7803e commit 35ba5a6
Show file tree
Hide file tree
Showing 3 changed files with 35 additions and 13 deletions.
7 changes: 4 additions & 3 deletions System/FilePath/Internal.hs
Original file line number Diff line number Diff line change
Expand Up @@ -129,8 +129,9 @@ import Data.List(stripPrefix, isSuffixOf, uncons, dropWhileEnd)
#define STRING String
#define FILEPATH FilePath
#else
import System.OsPath.Encoding.Internal.Hidden ( trySafe )
import Prelude (fromIntegral)
import Control.Exception ( SomeException, evaluate, try, displayException )
import Control.Exception ( SomeException, evaluate, displayException )
import Control.DeepSeq (force)
import GHC.IO (unsafePerformIO)
import qualified Data.Char as C
Expand Down Expand Up @@ -1273,12 +1274,12 @@ snoc str = \c -> str <> [c]
#ifdef WINDOWS
fromString :: P.String -> STRING
fromString str = P.either (P.error . P.show) P.id $ unsafePerformIO $ do
r <- try @SomeException $ GHC.withCStringLen (mkUTF16le ErrorOnCodingFailure) str $ \cstr -> packCStringLen cstr
r <- trySafe @SomeException $ GHC.withCStringLen (mkUTF16le ErrorOnCodingFailure) str $ \cstr -> packCStringLen cstr
evaluate $ force $ first displayException r
#else
fromString :: P.String -> STRING
fromString str = P.either (P.error . P.show) P.id $ unsafePerformIO $ do
r <- try @SomeException $ GHC.withCStringLen (mkUTF8 ErrorOnCodingFailure) str $ \cstr -> packCStringLen cstr
r <- trySafe @SomeException $ GHC.withCStringLen (mkUTF8 ErrorOnCodingFailure) str $ \cstr -> packCStringLen cstr
evaluate $ force $ first displayException r
#endif

Expand Down
29 changes: 25 additions & 4 deletions System/OsPath/Encoding/Internal/Hidden.hs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import GHC.IO.Buffer
import GHC.IO.Encoding.Failure
import GHC.IO.Encoding.Types
import Data.Bits
import Control.Exception (SomeException, try, Exception (displayException), evaluate)
import Control.Exception (SomeException, try, Exception (displayException), evaluate, SomeAsyncException(..), catch, fromException, toException, throwIO)
import qualified GHC.Foreign as GHC
import Data.Either (Either)
import GHC.IO (unsafePerformIO)
Expand All @@ -31,7 +31,7 @@ import Numeric (showHex)
import Foreign.C (CStringLen)
import Data.Char (chr)
import Foreign
import Prelude (FilePath)
import Prelude (FilePath, Either(..))
import GHC.IO.Encoding (getFileSystemEncoding)

-- -----------------------------------------------------------------------------
Expand Down Expand Up @@ -277,13 +277,13 @@ peekFilePathPosix fp = getFileSystemEncoding >>= \enc -> GHC.peekCStringLen enc
-- | Decode with the given 'TextEncoding'.
decodeWithTE :: TextEncoding -> BS8.ShortByteString -> Either EncodingException String
decodeWithTE enc ba = unsafePerformIO $ do
r <- try @SomeException $ BS8.useAsCStringLen ba $ \fp -> GHC.peekCStringLen enc fp
r <- trySafe @SomeException $ BS8.useAsCStringLen ba $ \fp -> GHC.peekCStringLen enc fp
evaluate $ force $ first (flip EncodingError Nothing . displayException) r

-- | Encode with the given 'TextEncoding'.
encodeWithTE :: TextEncoding -> String -> Either EncodingException BS8.ShortByteString
encodeWithTE enc str = unsafePerformIO $ do
r <- try @SomeException $ GHC.withCStringLen enc str $ \cstr -> BS8.packCStringLen cstr
r <- trySafe @SomeException $ GHC.withCStringLen enc str $ \cstr -> BS8.packCStringLen cstr
evaluate $ force $ first (flip EncodingError Nothing . displayException) r

-- -----------------------------------------------------------------------------
Expand Down Expand Up @@ -347,3 +347,24 @@ instance NFData EncodingException where

wNUL :: Word16
wNUL = 0x00

-- -----------------------------------------------------------------------------
-- Exceptions
--

-- | Like 'try', but rethrows async exceptions.
trySafe :: Exception e => IO a -> IO (Either e a)
trySafe ioA = catch action eHandler
where
action = do
v <- ioA
return (Right v)
eHandler e
| isAsyncException e = throwIO e
| otherwise = return (Left e)

isAsyncException :: Exception e => e -> Bool
isAsyncException e =
case fromException (toException e) of
Just (SomeAsyncException _) -> True
Nothing -> False
12 changes: 6 additions & 6 deletions System/OsString/Common.hs
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ import Control.Monad.Catch
import Data.ByteString.Internal
( ByteString )
import Control.Exception
( SomeException, try, displayException )
( SomeException, displayException )
import Control.DeepSeq ( force )
import Data.Bifunctor ( first )
import GHC.IO
Expand All @@ -70,7 +70,7 @@ import Language.Haskell.TH.Quote
( QuasiQuoter (..) )
import Language.Haskell.TH.Syntax
( Lift (..), lift )

import System.OsPath.Encoding.Internal.Hidden ( trySafe )

import GHC.IO.Encoding.Failure ( CodingFailureMode(..) )
#ifdef WINDOWS
Expand Down Expand Up @@ -116,10 +116,10 @@ encodeWith :: TextEncoding
-> Either EncodingException PLATFORM_STRING
encodeWith enc str = unsafePerformIO $ do
#ifdef WINDOWS
r <- try @SomeException $ GHC.withCStringLen enc str $ \cstr -> WindowsString <$> BS8.packCStringLen cstr
r <- trySafe @SomeException $ GHC.withCStringLen enc str $ \cstr -> WindowsString <$> BS8.packCStringLen cstr
evaluate $ force $ first (flip EncodingError Nothing . displayException) r
#else
r <- try @SomeException $ GHC.withCStringLen enc str $ \cstr -> PosixString <$> BS.packCStringLen cstr
r <- trySafe @SomeException $ GHC.withCStringLen enc str $ \cstr -> PosixString <$> BS.packCStringLen cstr
evaluate $ force $ first (flip EncodingError Nothing . displayException) r
#endif

Expand Down Expand Up @@ -176,7 +176,7 @@ decodeWith :: TextEncoding
-> PLATFORM_STRING
-> Either EncodingException String
decodeWith winEnc (WindowsString ba) = unsafePerformIO $ do
r <- try @SomeException $ BS8.useAsCStringLen ba $ \fp -> GHC.peekCStringLen winEnc fp
r <- trySafe @SomeException $ BS8.useAsCStringLen ba $ \fp -> GHC.peekCStringLen winEnc fp
evaluate $ force $ first (flip EncodingError Nothing . displayException) r
#else
-- | Decode a 'PosixString' with the specified encoding.
Expand All @@ -186,7 +186,7 @@ decodeWith :: TextEncoding
-> PLATFORM_STRING
-> Either EncodingException String
decodeWith unixEnc (PosixString ba) = unsafePerformIO $ do
r <- try @SomeException $ BS.useAsCStringLen ba $ \fp -> GHC.peekCStringLen unixEnc fp
r <- trySafe @SomeException $ BS.useAsCStringLen ba $ \fp -> GHC.peekCStringLen unixEnc fp
evaluate $ force $ first (flip EncodingError Nothing . displayException) r
#endif

Expand Down

0 comments on commit 35ba5a6

Please sign in to comment.