Skip to content

Commit b5fb044

Browse files
committed
Change moreRecentFile test to workaround races
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
1 parent afa460a commit b5fb044

File tree

3 files changed

+27
-4
lines changed

3 files changed

+27
-4
lines changed

Cabal/Distribution/Simple/Configure.hs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ import Distribution.Simple.BuildPaths
100100
( autogenModulesDir )
101101
import Distribution.Simple.Utils
102102
( die, warn, info, setupMessage
103-
, createDirectoryIfMissingVerbose, moreRecentFile
103+
, createDirectoryIfMissingVerbose, notLessRecentFile
104104
, intercalate, cabalVersion
105105
, writeFileAtomic
106106
, withTempFile )
@@ -281,7 +281,7 @@ showHeader pkgId = BLC8.unwords
281281
-- .cabal file.
282282
checkPersistBuildConfigOutdated :: FilePath -> FilePath -> IO Bool
283283
checkPersistBuildConfigOutdated distPref pkg_descr_file = do
284-
pkg_descr_file `moreRecentFile` (localBuildInfoFile distPref)
284+
pkg_descr_file `notLessRecentFile` (localBuildInfoFile distPref)
285285

286286
-- |@dist\/setup-config@
287287
localBuildInfoFile :: FilePath -> FilePath

Cabal/Distribution/Simple/PreProcess.hs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ import Distribution.Simple.LocalBuildInfo
5151
import Distribution.Simple.BuildPaths (autogenModulesDir,cppHeaderName)
5252
import Distribution.Simple.Utils
5353
( createDirectoryIfMissingVerbose, withUTF8FileContents, writeUTF8File
54-
, die, setupMessage, intercalate, copyFileVerbose, moreRecentFile
54+
, die, setupMessage, intercalate, copyFileVerbose, notLessRecentFile
5555
, findFileWithExtension, findFileWithExtension' )
5656
import Distribution.Simple.Program
5757
( Program(..), ConfiguredProgram(..), programPath
@@ -269,7 +269,7 @@ preprocessFile searchLoc buildLoc forSDist baseFile verbosity builtinSuffixes ha
269269
recomp <- case ppsrcFiles of
270270
Nothing -> return True
271271
Just ppsrcFile ->
272-
psrcFile `moreRecentFile` ppsrcFile
272+
psrcFile `notLessRecentFile` ppsrcFile
273273
when recomp $ do
274274
let destDir = buildLoc </> dirName srcStem
275275
createDirectoryIfMissingVerbose verbosity True destDir

Cabal/Distribution/Simple/Utils.hs

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,8 @@ module Distribution.Simple.Utils (
8787
-- * modification time
8888
moreRecentFile,
8989
existsAndIsMoreRecentThan,
90+
notLessRecentFile,
91+
existsAndIsNotLessRecentThan,
9092

9193
-- * temp files and dirs
9294
TempFileOptions(..), defaultTempFileOptions,
@@ -785,6 +787,27 @@ existsAndIsMoreRecentThan a b = do
785787
then return False
786788
else a `moreRecentFile` b
787789

790+
-- | Variant of 'moreRecentFile' comparing times using '>='
791+
-- comparision instead of '>'. This reduces race-conditions for
792+
-- generated files when the system time granularity is too low.
793+
--
794+
notLessRecentFile :: FilePath -> FilePath -> IO Bool
795+
notLessRecentFile a b = do
796+
exists <- doesFileExist b
797+
if not exists
798+
then return True
799+
else do tb <- getModificationTime b
800+
ta <- getModificationTime a
801+
return (ta >= tb)
802+
803+
-- | Like 'notLessRecentFile', but also checks that the first file exists.
804+
existsAndIsNotLessRecentThan :: FilePath -> FilePath -> IO Bool
805+
existsAndIsNotLessRecentThan a b = do
806+
exists <- doesFileExist a
807+
if not exists
808+
then return False
809+
else a `notLessRecentFile` b
810+
788811
----------------------------------------
789812
-- Copying and installing files and dirs
790813

0 commit comments

Comments
 (0)