summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthew Pickering <matthewtpickering@gmail.com>2022-03-30 09:38:13 +0100
committerMatthew Pickering <matthewtpickering@gmail.com>2022-04-01 11:10:23 +0100
commit8ca7ab81b4f2344116646f849843e8b0fc6fd4b7 (patch)
tree7e0874800f00b1675e5ff1a9b0306749db2a7334
parentad6cd16515101c331123bd3566b9c0861a6cac5f (diff)
downloadhaskell-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.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 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