Skip to content

hGetContents does not close handle on exception #712

Description

@julmb

The documentation for Data.Text.IO.hGetContents promises

The 'Handle' is closed once the contents have been read, or if an exception is thrown.

However, this seems to not be the case:

import Control.Exception
import Data.Text.IO qualified as T
import System.IO

main :: IO ()
main = do
    handle <- openFile "/bin/bash" ReadMode
    result <- try @IOException $ T.hGetContents handle
    closed <- hIsClosed handle
    print handle >> print result >> print closed

On my system (ghc-9.12.2, text-2.1.4), this yields

{handle: /bin/bash}
Left /bin/bash: hGetContents: invalid argument (cannot decode byte sequence starting from 224)
False

As far as I can tell, this also affects Data.Text.IO.readFile, which uses openFile instead of withFile and so the handle is not closed there either. System.IO.readFile' uses withFile and has a comment acknowledging that this should not be necessary:

There's a bit of overkill here—both withFile and hGetContents' will close the file in the end.

I cannot say with 100% certainty, but I believe this to be the root cause of a "resource exhausted (Too many open files)" exception in my application.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions