Home > Back-end >  Closing file handle causes troubles in Haskell
Closing file handle causes troubles in Haskell

Time:10-11

I have the following code for loading contents of the file and parse it with aeson into an object:

  loadFromFile filename = do
    fileHandle <- openFile ( dataDir    "/"    filename ) ReadMode
    contents <- B.hGetContents fileHandle
    let result = fromMaybe initial $! JSON.decode contents in do
      hClose fileHandle
      return $! result 

The problem with this code is that it causes following errors:

filename.json: hGetBufSome: illegal operation (handle is closed)
filename.json: hGetBufSome: illegal operation (handle is closed)

I do not quite understand why it thinks file handle is closed. I am reading it before closing the handle after all. Or is lazy evaluation affecting the order of execution? I tried adding corresponding $! operators to make it evaluate sooner, but it does not help. If I remove hClose fileHandle line, then I start getting sporadic errors of the following kind:

filename.json: openFile: resource busy (file is locked)

If somebody knows how to fix this catch22, I would really appreciate it. Thanks!

CodePudding user response:

Instead of forcing the result after closing the handle, you should force the result before closing the handle, here's how you can do that with BangPatterns:

  loadFromFile filename = do
    fileHandle <- openFile ( dataDir    "/"    filename ) ReadMode
    contents <- B.hGetContents fileHandle
    let !result = fromMaybe initial $! JSON.decode contents
    hClose fileHandle
    return result

In this case a deepseq is not required, because (I believe) the decode function will process the whole input before deciding whether to return Nothing or Just ..., so forcing only that one level is enough.

And, if possible, it is better to avoid handles entirely:

  loadFromFile filename = do
    contents <- B.readFile ( dataDir    "/"    filename )
    return $! fromMaybe initial $! JSON.decode contents
  • Related