summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthew Pickering <matthewtpickering@gmail.com>2022-03-30 09:38:13 +0100
committerZubin Duggal <zubin.duggal@gmail.com>2022-07-11 11:25:55 +0530
commitcd601182cbf8067d529deb95e08a8a029b41481d (patch)
tree5511930dbe8e6b113ee65b891f18c86ff2de4c40
parent7860464a37ae4cc61f3fb4f1348e975a3b212886 (diff)
downloadhaskell-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.hs6
-rw-r--r--hadrian/src/Rules/Register.hs7
-rw-r--r--hadrian/src/Settings/Builders/GhcPkg.hs10
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