Opened 12 years ago

Closed 11 years ago

Last modified 10 years ago

#2134 closed bug (fixed)

Intermittent file locking bug in installPackage.hs

Reported by: gw Owned by: duncan
Priority: normal Milestone: 6.8.3
Component: libraries (other) Version: 6.8.2
Keywords: Cc: duncan.coutts@…
Operating System: Unknown/Multiple Architecture: Unknown/Multiple
Type of failure: None/Unknown Test Case:
Blocked By: Blocking:
Related Tickets: Differential Rev(s):
Wiki Page:


After fixing the bug in ticket #1992, I still saw lock occasional lock errors building ghc. Dumping all of the fd/dev/inode info in lockFile and unlockFile showed that the lock hash tables were not inconsistent, as they had been in #1992, but that a write lock was being placed on a file before a read lock was released.

The culprit is the reading of the configuration in libraries/installPackage.hs (lbi <- getConfig verbosity). This ultimately uses tryGetConfigStateFile from libraries/Cabal/Distribution/Simple/Configure.hs. And this function uses readFile to read in the configuration file.

The dump of fd/dev/inode info showed that readFile was acquiring a lock that was not released before the end of the program. Occasionally, there was an attempt to obtain a write lock on the same dev/inode, leading to a lock error. It looks as if this is the laziness problem with readFile noted in the IO library documentation.

Making the read of the configuration file strict and explicitly closing the handle fixes the problem for me. Here is the patch:

--- libraries/Cabal/Distribution/Simple/Configure.hs.sav	2008-03-01 17:01:39.000000000 -0500
+++ libraries/Cabal/Distribution/Simple/Configure.hs	2008-03-01 17:04:25.000000000 -0500
@@ -130,7 +130,7 @@
 import qualified System.Info
     ( os, arch )
 import System.IO
-    ( hPutStrLn, stderr )
+    ( hPutStrLn, stderr, openFile, IOMode(..), hGetContents, hClose )
 import Text.PrettyPrint.HughesPJ
     ( comma, punctuate, render, nest, sep )
@@ -146,7 +146,9 @@
   let dieMsg = "error reading " ++ filename ++ 
                "; run \"setup configure\" command?\n"
   if (not e) then return $ Left dieMsg else do 
-    str <- readFile filename
+    hdl <- openFile filename ReadMode
+    str <- hGetContents hdl >>= \s -> last s `seq` return s
+    hClose hdl
     case reads str of
       [(bi,_)] -> return $ Right bi
       _        -> return $ Left  dieMsg

I'm still not certain why the bug occurs only some of the time, and whether it is OS dependent. But readFile's holding of the lock for an unpredictable time is just asking for trouble.

Change History (7)

comment:1 Changed 12 years ago by simonmar

Component: Compilerlibraries (other)
difficulty: Easy (1 hr)
Milestone: 6.8.3

We should make sure this fix is in the Cabal we ship with 6.8.3.

comment:2 Changed 11 years ago by igloo

Cc: duncan.coutts@… added

It looks like we need to merge

[fix 'clean' bug on windows caused by leaked Handle.
Andrea Vezzosi <>**20080318161237
 Using readFile to read dist/setup-config keeps the Handle open when we try to delete the file, causing an error. 
 So we instead read the file strictly and close the Handle early.

but I'm not sure which Cabal repo it should be merged into. Duncan?

comment:3 Changed 11 years ago by duncan

Owner: set to duncan

Yep, to cabal-branches/cabal-1.2

We'll make a point release on that branch for ghc-6.8.3, probably since we do not expect to push any patches that involve API changes.

comment:4 Changed 11 years ago by igloo

Resolution: fixed
Status: newclosed

OK, I've merged the patch.

comment:5 Changed 11 years ago by simonmar

Architecture: UnknownUnknown/Multiple

comment:6 Changed 11 years ago by simonmar

Operating System: UnknownUnknown/Multiple

comment:7 Changed 10 years ago by simonmar

difficulty: Easy (1 hr)Easy (less than 1 hour)
Note: See TracTickets for help on using tickets.