1

My program reads a line from a network socket and writes it to disc. Since lines can be really long and strings had terrible performance I started using lazy byte strings. Now it seems that Haskell will go past hClose on disc file handle without actually flushing whole byte string to disc, so doing:

  • open file for writing
  • write byte string to file with hPut
  • close file
  • open file for reading

usually results in openFile: resource busy (file is locked).

Is it possible to enforce evaluation and wait for the whole byte string to be written before closing the file, so I can be sure that the file is actually closed after that operation?

Marek Sapota
  • 20,103
  • 3
  • 34
  • 47

2 Answers2

0

Since the only other answer is of the "use something else" variety I'm posting my own solution. Using this function after hClose will hang the thread until lazy write is done.

waitForLazyIO location = do
    t <- liftIO $ try $ openFile location AppendMode
    handle t
    where
        handle (Right v) = hClose v
        handle (Left e)
            -- Add some sleep if you expect the write operation to be slow.
            | isAlreadyInUseError e = waitForLazyIO location
            | otherwise = throwError $ show e
Marek Sapota
  • 20,103
  • 3
  • 34
  • 47
  • This might work, but frankly it is a hack, not really up to the usual standards for haskell software. The lazy IO path is full of traps because the concept is broken quiet deeply. At the moment, the only viable option for constant-memory IO manipulations is the family of left-fold enumerators, of which [conduit](http://hackage.haskell.org/package/conduit) is one popular member. – Paul R Apr 13 '12 at 15:13
0

Try using strict i/o with strict byte strings instead of lazy i/o and lazy byte strings.

If that turns out to be too inefficient, try using conduit or a similar package.

dave4420
  • 46,404
  • 6
  • 118
  • 152