[Git][ghc/ghc][master] 3 commits: Correct `hIsReadable` and `hIsWritable` for duplex handles
Marge Bot pushed to branch master at Glasgow Haskell Compiler / GHC Commits: 598db847 by Wolfgang Jeltsch at 2026-03-06T06:25:25-05:00 Correct `hIsReadable` and `hIsWritable` for duplex handles This contribution implements CLC proposal #371. It changes `hIsReadable` and `hIsWritable` such that they always throw a respective exception when encountering a closed or semi-closed handle, not just in the case of a file handle. - - - - - b90201e5 by Wolfgang Jeltsch at 2026-03-06T06:25:25-05:00 Document `SemiClosedHandle` - - - - - c9df72b5 by Wolfgang Jeltsch at 2026-03-06T06:25:25-05:00 Tell users what “semi-closed” means for duplex handles - - - - - 4 changed files: - libraries/base/changelog.md - libraries/ghc-internal/src/GHC/Internal/IO/Handle.hs - libraries/ghc-internal/src/GHC/Internal/IO/Handle/Text.hs - libraries/ghc-internal/src/GHC/Internal/IO/Handle/Types.hs Changes: ===================================== libraries/base/changelog.md ===================================== @@ -26,6 +26,7 @@ * Add a new module `System.IO.OS` with operations for obtaining operating-system handles (file descriptors, Windows handles). ([CLC proposal #369](https://github.com/haskell/core-libraries-committee/issues/369)) * Evaluate backtraces for "error" exceptions at the moment they are thrown. ([CLC proposal #383](https://github.com/haskell/core-libraries-committee/issues/383)) * Hide implementation details when throwing exceptions in throw and throwSTM. ([CLC proposal #387](https://github.com/haskell/core-libraries-committee/issues/387)) + * Change `hIsReadable` and `hIsWritable` such that they always throw a respective exception when encountering a closed or semi-closed handle, not just in the case of a file handle. ([CLC proposal #371](github.com/haskell/core-libraries-committee/issues/371)) ## 4.22.0.0 *TBA* * Shipped with GHC 9.14.1 ===================================== libraries/ghc-internal/src/GHC/Internal/IO/Handle.hs ===================================== @@ -502,9 +502,14 @@ hIsClosed handle = -- | @'hIsReadable' hdl@ returns whether it is possible to read from the handle. hIsReadable :: Handle -> IO Bool -hIsReadable (DuplexHandle _ _ _) = return True -hIsReadable handle = - withHandle_ "hIsReadable" handle $ \ handle_ -> do +hIsReadable handle@(FileHandle _ var) + = hIsReadable' handle var +hIsReadable handle@(DuplexHandle _ readingVar _) + = hIsReadable' handle readingVar + +hIsReadable' :: Handle -> MVar Handle__ -> IO Bool +hIsReadable' handle readingVar = + withHandle_' "hIsReadable" handle readingVar $ \ handle_ -> do case haType handle_ of ClosedHandle -> ioe_closedHandle SemiClosedHandle -> ioe_semiclosedHandle @@ -512,9 +517,14 @@ hIsReadable handle = -- | @'hIsWritable' hdl@ returns whether it is possible to write to the handle. hIsWritable :: Handle -> IO Bool -hIsWritable (DuplexHandle _ _ _) = return True -hIsWritable handle = - withHandle_ "hIsWritable" handle $ \ handle_ -> do +hIsWritable handle@(FileHandle _ var) + = hIsWritable' handle var +hIsWritable handle@(DuplexHandle _ _ writingVar) + = hIsWritable' handle writingVar + +hIsWritable' :: Handle -> MVar Handle__ -> IO Bool +hIsWritable' handle writingVar = + withHandle_' "hIsWritable" handle writingVar $ \ handle_ -> do case haType handle_ of ClosedHandle -> ioe_closedHandle SemiClosedHandle -> ioe_semiclosedHandle ===================================== libraries/ghc-internal/src/GHC/Internal/IO/Handle/Text.hs ===================================== @@ -361,19 +361,18 @@ unpack_nl !buf !r !w acc0 -- ----------------------------------------------------------------------------- -- hGetContents --- hGetContents on a DuplexHandle only affects the read side: you can --- carry on writing to it afterwards. - -- | Computation 'hGetContents' @hdl@ returns the list of characters -- corresponding to the unread portion of the channel or file managed -- by @hdl@, which is put into an intermediate state, /semi-closed/. --- In this state, @hdl@ is effectively closed, --- but items are read from @hdl@ on demand and accumulated in a special --- list returned by 'hGetContents' @hdl@. +-- In this state, @hdl@ is treated like a closed handle, with the +-- following exceptions: +-- +-- * Characters can be read from @hdl@ by evaluating portions of the +-- list returned by 'hGetContents' @hdl@. +-- * If the handle allows for independent reading and writing, as it is +-- the case for socket handles, writing continues to be possible. -- --- Any operation that fails because a handle is closed, --- also fails if a handle is semi-closed. The only exception is --- 'GHC.Internal.System.IO.hClose'. A semi-closed handle becomes closed: +-- A semi-closed handle becomes closed: -- -- * if 'GHC.Internal.System.IO.hClose' is applied to it; -- ===================================== libraries/ghc-internal/src/GHC/Internal/IO/Handle/Types.hs ===================================== @@ -157,6 +157,7 @@ data BufferList e data HandleType = ClosedHandle | SemiClosedHandle + -- ^ See the documentation of 'GHC.IO.Handle.Text.hGetContents'. | ReadHandle | WriteHandle | AppendHandle View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/7d64031bbb2e37d4f10e535f8e47e62... -- View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/7d64031bbb2e37d4f10e535f8e47e62... You're receiving this email because of your account on gitlab.haskell.org.
participants (1)
-
Marge Bot (@marge-bot)