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.
The documentation for
Data.Text.IO.hGetContentspromisesHowever, this seems to not be the case:
On my system (
ghc-9.12.2,text-2.1.4), this yieldsAs far as I can tell, this also affects
Data.Text.IO.readFile, which usesopenFileinstead ofwithFileand so the handle is not closed there either.System.IO.readFile'useswithFileand has a comment acknowledging that this should not be necessary: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.