Skip to content

Commit

Permalink
Merge branch '1.4.1XX-no-async' into 1.4.1XX
Browse files Browse the repository at this point in the history
  • Loading branch information
hasufell committed Nov 17, 2024
2 parents b68e3e0 + 29270d7 commit 5a2cf94
Show file tree
Hide file tree
Showing 5 changed files with 42 additions and 14 deletions.
7 changes: 4 additions & 3 deletions System/FilePath/Internal.hs
Original file line number Diff line number Diff line change
Expand Up @@ -130,9 +130,10 @@ import Data.List(stripPrefix, isSuffixOf, uncons, dropWhileEnd)
#define FILEPATH FilePath
#else
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 System.OsPath.Encoding.Internal (trySafe)
import qualified Data.Char as C
#ifdef WINDOWS
import GHC.IO.Encoding.Failure ( CodingFailureMode(..) )
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
30 changes: 26 additions & 4 deletions System/OsPath/Encoding/Internal.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, SomeAsyncException(..), Exception (displayException), evaluate, catch, throwIO, toException, fromException)
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,25 @@ 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

11 changes: 6 additions & 5 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 @@ -73,6 +73,7 @@ import Language.Haskell.TH.Syntax


import GHC.IO.Encoding.Failure ( CodingFailureMode(..) )
import System.OsPath.Encoding.Internal (trySafe)
#ifdef WINDOWS
import System.OsPath.Encoding
import System.IO
Expand Down Expand Up @@ -116,10 +117,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 +177,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 +187,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
6 changes: 5 additions & 1 deletion changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,11 @@

_Note: below all `FilePath` values are unquoted, so `\\` really means two backslashes._

## 1.4.101.0. *Jan 2024*
## 1.4.102.0 *Nov 2024*

* Don't catch async exceptions in internal functions wrt https://github.com/haskell/os-string/issues/22

## 1.4.101.0 *Jan 2024*

* Backport bugfix for [`splitFileName`](https://github.com/haskell/filepath/issues/219) on windows

Expand Down
2 changes: 1 addition & 1 deletion filepath.cabal
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
cabal-version: 2.2
name: filepath
version: 1.4.101.0
version: 1.4.102.0

-- NOTE: Don't forget to update ./changelog.md
license: BSD-3-Clause
Expand Down

0 comments on commit 5a2cf94

Please sign in to comment.