Ticket #1994 (closed bug: fixed)
Data.ByteStirng.Lazy.hGetContents doesn't unlock i-node
I found that Data.ByteStirng?.Lazy.hGetContents doesn't unlock i-node even after retreiving whole contents. Because of this and the fact that file locking mechanism of GHC uses i-node, sometimes it causes a problem whose cause is hard to find.
See this example assuming file 'a' already exists:
testB = forM [1..] $ \_ -> do r <- B.readFile "a" >>= \r -> return $! B.length r `seq` r B.writeFile "b" (B8.pack "abc") renameFile "b" "a"
When I run this test on GHCi, it shows this error:
*Main> testB *** Exception: b: openBinaryFile: resource busy (file is locked)
I presume that this error happened because:
- readFile locks the i-node of 'a' and continues to lock after reading whole contents
- writeFile writes contents to 'b'
- Maybe GC runs and closes the handle but doesn't unlock i-node
- renaming 'b' to 'a' causes free the i-node of 'a'
- readFile locks another i-node of 'a'
- writeFile reuses the first i-node of 'a' which is still locked
It is very difficult to find that readFile causes a problem, because an error occures in writeFile.
I'm not sure this is a problem of ByteString? or GC, but this problem doesn't occur when I use System.IO.hGetContents because it closes the handle and unlocks the i-node after retrieving whole contents.