diff options
author | Matthew Pickering <matthewtpickering@gmail.com> | 2022-03-30 09:38:13 +0100 |
---|---|---|
committer | Matthew Pickering <matthewtpickering@gmail.com> | 2022-04-01 11:10:23 +0100 |
commit | 8ca7ab81b4f2344116646f849843e8b0fc6fd4b7 (patch) | |
tree | 7e0874800f00b1675e5ff1a9b0306749db2a7334 | |
parent | ad6cd16515101c331123bd3566b9c0861a6cac5f (diff) | |
download | haskell-8ca7ab81b4f2344116646f849843e8b0fc6fd4b7.tar.gz |
hadrian: Fix race involving empty package databases
There was a small chance of a race occuring between the small window of
1. The first package (.conf) file get written into the database
2. hadrian calling "ghc-pkg recache" to refresh the package.conf file
In this window the package database would contain rts.conf but not a
package.cache file, and therefore if ghc was invoked it would error
because it was missing.
To solve this we call "ghc-pkg recache" at when the database is created
by shake by writing the stamp file into the database folder. This also
creates the package.cache file and so avoids the possibility of this
race.
-rw-r--r-- | hadrian/src/Builder.hs | 6 | ||||
-rw-r--r-- | hadrian/src/Rules/Register.hs | 7 | ||||
-rw-r--r-- | hadrian/src/Settings/Builders/GhcPkg.hs | 10 |
3 files changed, 18 insertions, 5 deletions
diff --git a/hadrian/src/Builder.hs b/hadrian/src/Builder.hs index 0ff400288d..6d95ca5573 100644 --- a/hadrian/src/Builder.hs +++ b/hadrian/src/Builder.hs @@ -100,10 +100,10 @@ instance Hashable ConfigurationInfo instance NFData ConfigurationInfo -- TODO: Do we really need all these modes? Why do we need 'Dependencies'? We --- can extract dependencies using the Cabal library. Note: we used to also have --- the @Init@ mode for initialising a new package database but we've deleted it. +-- can extract dependencies using the Cabal library. -- | 'GhcPkg' can initialise a package database and register packages in it. -data GhcPkgMode = Copy -- ^ Copy a package from one database to another. +data GhcPkgMode = Init -- ^ Initialise an empty package database + | Copy -- ^ Copy a package from one database to another. | Dependencies -- ^ Compute package dependencies. | Unregister -- ^ Unregister a package. | Update -- ^ Update a package. diff --git a/hadrian/src/Rules/Register.hs b/hadrian/src/Rules/Register.hs index c2091e0fda..cefdf04cb7 100644 --- a/hadrian/src/Rules/Register.hs +++ b/hadrian/src/Rules/Register.hs @@ -90,7 +90,12 @@ registerPackageRules rs stage = do root <- buildRootRules -- Initialise the package database. - root -/- relativePackageDbPath stage -/- packageDbStamp %> \stamp -> + root -/- relativePackageDbPath stage -/- packageDbStamp %> \stamp -> do + -- This command initialises the package.cache file to avoid a race where + -- a package gets registered but there's not a package.cache file (which + -- leads to errors in GHC). + buildWithResources rs $ + target (Context stage compiler vanilla) (GhcPkg Init stage) [] [] writeFileLines stamp [] -- Register a package. diff --git a/hadrian/src/Settings/Builders/GhcPkg.hs b/hadrian/src/Settings/Builders/GhcPkg.hs index b94fbca815..752f1718da 100644 --- a/hadrian/src/Settings/Builders/GhcPkg.hs +++ b/hadrian/src/Settings/Builders/GhcPkg.hs @@ -4,7 +4,15 @@ import Settings.Builders.Common ghcPkgBuilderArgs :: Args ghcPkgBuilderArgs = mconcat - [ builder (GhcPkg Copy) ? do + [ builder (GhcPkg Init) ? do + stage <- getStage + pkgDb <- expr $ packageDbPath stage + -- Confusingly calls recache rather than init because shake "creates" + -- the package db by virtue of creating the path to it, so we just recache + -- to create the package.cache file. + mconcat [ use_db pkgDb, arg "recache" ] + + , builder (GhcPkg Copy) ? do verbosity <- expr getVerbosity stage <- getStage pkgDb <- expr $ packageDbPath stage |