Andreas Klebinger pushed to branch wip/andreask/hadrian_race at Glasgow Haskell Compiler / GHC Commits: b2e71591 by Andreas Klebinger at 2026-03-05T13:09:16+01:00 Some fixes - - - - - 2 changed files: - libraries/ghc-boot/GHC/Unit/Database.hs - utils/ghc-pkg/Main.hs Changes: ===================================== libraries/ghc-boot/GHC/Unit/Database.hs ===================================== @@ -336,11 +336,10 @@ withLockedPackageDb mode file = (lockPackageDbWith (lock_mode mode) file) unlockPackageDb where - bracket_for_mode = + bracket_for_mode = case mode of - DbOpenReadOnly -> bracket - DbOpenReadWrite -> bracketOnError - where + DbOpenReadOnly -> bracket + DbOpenReadWrite{} -> bracketOnError lock_mode :: DbOpenMode m t -> LockMode lock_mode DbOpenReadOnly = SharedLock lock_mode DbOpenReadWrite{} = ExclusiveLock @@ -405,6 +404,14 @@ data DbMode = DbReadOnly | DbReadWrite deriving Eq -- | 'DbOpenMode' holds a value of type @t@ but only in 'DbReadWrite' mode. So -- it is like 'Maybe' but with a type argument for the mode to enforce that the -- mode is used consistently. +-- +-- We use the argument to DbOpenReadWrite only when modifying the DB for two uses: +-- * Storing the Din two cases: +-- When modifying the DB however the lock is meant to outlive +-- intermittent read operations. Which is why for writes we typically store the lock in DbOpenMode. +-- and pass it along the call path. +-- +-- See Note [ghc-pkg database locking] and withLockedPackageDb data DbOpenMode (mode :: DbMode) t where DbOpenReadOnly :: DbOpenMode 'DbReadOnly t DbOpenReadWrite :: t -> DbOpenMode 'DbReadWrite t @@ -430,7 +437,7 @@ isDbOpenReadMode = \case -- readPackageDbForGhc :: FilePath -> IO [DbUnitInfo] readPackageDbForGhc file = do - hPutStrLn stderr $ "readPackageDbForGhc:" ++ show file + -- hPutStrLn stderr $ "readPackageDbForGhc:" ++ show file withLockedPackageDb DbOpenReadOnly file $ \_ -> do decodeFromFile file DbOpenReadOnly getDbForGhc >>= \case (pkgs, DbOpenReadOnly) -> return pkgs @@ -450,10 +457,7 @@ readPackageDbForGhc file = do -- -- The incoming mode carries the exclusive lock if we are in R/W mode. -- --- If we open the package db in read only mode, we get its contents. Otherwise --- we additionally receive a PackageDbLock that represents a lock on the --- database, so that we can safely update it later. --- +-- Returns the lock on the db as-is. readPackageDbForGhcPkg :: Binary pkgs => FilePath -> DbOpenMode mode PackageDbLock -> IO (pkgs, DbOpenMode mode PackageDbLock) readPackageDbForGhcPkg file mode = @@ -545,15 +549,9 @@ headerMagic = BS.Char8.pack "\0ghcpkg\0" -- which it returns unchanged. decodeFromFile :: FilePath -> DbOpenMode mode PackageDbLock -> Get pkgs -> IO (pkgs, DbOpenMode mode PackageDbLock) -decodeFromFile file mode decoder = case mode of - -- DB is locked with shared access already, we just do the read. - DbOpenReadOnly -> do - (, DbOpenReadOnly) <$> decodeFileContents - DbOpenReadWrite{} -> do - -- When we open the package db in read/write mode, we receive an exclusive lock - -- on the database via the mode and return it so we can keep it for the duration of the - -- update. - -- If an exception is raised the caller releases the lock. +decodeFromFile file mode decoder = + -- Return incoming lock together with the result. + -- See Note [ghc-pkg database locking] (, mode) <$> decodeFileContents where decodeFileContents = withBinaryFile file ReadMode $ \hnd -> ===================================== utils/ghc-pkg/Main.hs ===================================== @@ -885,8 +885,9 @@ database in both modes: - In read-only mode, we take a *shared* lock before reading and unlock afterwards. Locking is needed to avoid a concurrent invocation of ghc-pkg deleting files from the db before we manage to read them. This occasionally happened in #22870. - (Note that, historically, we used to only lock the package db during reads on - Windows, but the justification seemed insufficient given #22870. See also #16773.) + (Note that, historically, only windows used to lock the package db during reads, + but the justification seemed insufficient given #22870. So now we always lock + even for reads. See also #16773.) - In read-write mode, we take an **exclusive** lock on the package database. However, we don't automatically release the lock after the inner action completes @@ -970,20 +971,13 @@ readParseDatabase verbosity mb_user_conf mode use_cache path where confs = map (path </>) $ filter (".conf" `isSuffixOf`) fs - -- Read the package db, potentially locking the .cache file for r/w mode. + -- Read the package db, using the given lock ignore_cache :: PackageDbLock -> (FilePath -> IO ()) -> IO (PackageDB mode) ignore_cache lock checkTime = do - -- If we're opening for modification, we need to acquire a - -- lock even if we don't open the cache now, because we are - -- going to modify it later. - - -- mode' <- F.mapM (const $ GhcPkg.lockPackageDb cache) mode - let doFile f = do checkTime f parseSingletonPackageConf verbosity f pkgs <- mapM doFile confs - -- mkPackageDB pkgs mode' mkPackageDB pkgs (modeWithLock lock mode) -- We normally report cache errors for read-only commands, View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/b2e71591480edf95b3d48547c98c831d... -- View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/b2e71591480edf95b3d48547c98c831d... You're receiving this email because of your account on gitlab.haskell.org.
participants (1)
-
Andreas Klebinger (@AndreasK)