diff options
author | Matthew Pickering <matthewtpickering@gmail.com> | 2022-03-30 09:38:13 +0100 |
---|---|---|
committer | Zubin Duggal <zubin.duggal@gmail.com> | 2022-07-11 11:25:55 +0530 |
commit | cd601182cbf8067d529deb95e08a8a029b41481d (patch) | |
tree | 5511930dbe8e6b113ee65b891f18c86ff2de4c40 | |
parent | 7860464a37ae4cc61f3fb4f1348e975a3b212886 (diff) | |
download | haskell-cd601182cbf8067d529deb95e08a8a029b41481d.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.
(cherry picked from commit 8ca7ab81b4f2344116646f849843e8b0fc6fd4b7)
-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 11a495c65b..de4a7ad0b6 100644 --- a/hadrian/src/Builder.hs +++ b/hadrian/src/Builder.hs @@ -96,10 +96,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 6bbae7e0bd..2a51c7d4e4 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 8b9d28f6b5..20d7a59fc0 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 |