Skip to content

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:

  1. readFile locks the i-node of 'a' and continues to lock after reading whole contents
  2. writeFile writes contents to 'b'
  3. Maybe GC runs and closes the handle but doesn't unlock i-node
  4. renaming 'b' to 'a' causes free the i-node of 'a'
  5. readFile locks another i-node of 'a'
  6. 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.

Trac metadata
Trac field Value
Version 6.8.2
Type Bug
TypeOfFailure OtherFailure
Priority normal
Resolution Unresolved
Component libraries (other)
Test case
Differential revisions
BlockedBy
Related
Blocking
CC snak@snak.org
Operating system
Architecture x86
To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information