Skip to content

Commit

Permalink
Change moreRecentFile test to workaround races
Browse files Browse the repository at this point in the history
This adds `notLessRecentFile a b` to return true not only when `a`
is younger than `b`, but also when `a` is exactly the same age of `b`, as
that case is subject to race-conditions (if the system time granularity
is too low), and it's better to err on assuming it needs to be regenerated.

This is an attempt to provide a pragmatic workaround for #2311
  • Loading branch information
hvr committed Jan 14, 2015
1 parent afa460a commit b5fb044
Show file tree
Hide file tree
Showing 3 changed files with 27 additions and 4 deletions.
4 changes: 2 additions & 2 deletions Cabal/Distribution/Simple/Configure.hs
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ import Distribution.Simple.BuildPaths
( autogenModulesDir )
import Distribution.Simple.Utils
( die, warn, info, setupMessage
, createDirectoryIfMissingVerbose, moreRecentFile
, createDirectoryIfMissingVerbose, notLessRecentFile
, intercalate, cabalVersion
, writeFileAtomic
, withTempFile )
Expand Down Expand Up @@ -281,7 +281,7 @@ showHeader pkgId = BLC8.unwords
-- .cabal file.
checkPersistBuildConfigOutdated :: FilePath -> FilePath -> IO Bool
checkPersistBuildConfigOutdated distPref pkg_descr_file = do
pkg_descr_file `moreRecentFile` (localBuildInfoFile distPref)
pkg_descr_file `notLessRecentFile` (localBuildInfoFile distPref)

-- |@dist\/setup-config@
localBuildInfoFile :: FilePath -> FilePath
Expand Down
4 changes: 2 additions & 2 deletions Cabal/Distribution/Simple/PreProcess.hs
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ import Distribution.Simple.LocalBuildInfo
import Distribution.Simple.BuildPaths (autogenModulesDir,cppHeaderName)
import Distribution.Simple.Utils
( createDirectoryIfMissingVerbose, withUTF8FileContents, writeUTF8File
, die, setupMessage, intercalate, copyFileVerbose, moreRecentFile
, die, setupMessage, intercalate, copyFileVerbose, notLessRecentFile
, findFileWithExtension, findFileWithExtension' )
import Distribution.Simple.Program
( Program(..), ConfiguredProgram(..), programPath
Expand Down Expand Up @@ -269,7 +269,7 @@ preprocessFile searchLoc buildLoc forSDist baseFile verbosity builtinSuffixes ha
recomp <- case ppsrcFiles of
Nothing -> return True
Just ppsrcFile ->
psrcFile `moreRecentFile` ppsrcFile
psrcFile `notLessRecentFile` ppsrcFile
when recomp $ do
let destDir = buildLoc </> dirName srcStem
createDirectoryIfMissingVerbose verbosity True destDir
Expand Down
23 changes: 23 additions & 0 deletions Cabal/Distribution/Simple/Utils.hs
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,8 @@ module Distribution.Simple.Utils (
-- * modification time
moreRecentFile,
existsAndIsMoreRecentThan,
notLessRecentFile,
existsAndIsNotLessRecentThan,

-- * temp files and dirs
TempFileOptions(..), defaultTempFileOptions,
Expand Down Expand Up @@ -785,6 +787,27 @@ existsAndIsMoreRecentThan a b = do
then return False
else a `moreRecentFile` b

-- | Variant of 'moreRecentFile' comparing times using '>='
-- comparision instead of '>'. This reduces race-conditions for
-- generated files when the system time granularity is too low.
--
notLessRecentFile :: FilePath -> FilePath -> IO Bool
notLessRecentFile a b = do
exists <- doesFileExist b
if not exists
then return True
else do tb <- getModificationTime b
ta <- getModificationTime a
return (ta >= tb)

-- | Like 'notLessRecentFile', but also checks that the first file exists.
existsAndIsNotLessRecentThan :: FilePath -> FilePath -> IO Bool
existsAndIsNotLessRecentThan a b = do
exists <- doesFileExist a
if not exists
then return False
else a `notLessRecentFile` b

----------------------------------------
-- Copying and installing files and dirs

Expand Down

0 comments on commit b5fb044

Please sign in to comment.