Bad error message when using lazy IO to read from closed handle
Today I accidentally wrote this code:
import System.IO
import Data.ByteString.Lazy as BSL
filesEqual :: FilePath -> FilePath -> IO Bool
filesEqual f1 f2 = do
equal <- withBinaryFile f1 ReadMode $ \h1 ->
withBinaryFile f2 ReadMode $ \h2 -> do
c1 <- BSL.hGetContents h1
c2 <- BSL.hGetContents h2
return (c1 == c2)
return $! equal
main = filesEqual "test.hs" "test.hs" >>= print
The problem is that I should have done the forcing before the files are closed:
return $! (c1 == c2)
I got the incredibly unhelpful error message
test: test.hs: illegal operation
It took me 2 hours and strace to find out what was going on, especially because around every file open() there are multiple things that map top IllegalOperation (e.g. the ENOTTY from the ioctl that checks whether the device is a TTY).
Can we give a better error message here, at least mentioning that the problem has to do with closed (and GC'd) handles?