Commit f86de44d authored by Ben Gamari's avatar Ben Gamari Committed by Ben Gamari

ghc-pkg: Try opening lockfiles in read-write mode first

As pointed out in #13945, some filesystems only allow allow exclusive
locks if the fd being locked was opened for write access. This causes
ghc-pkg to fail as it first attempts to open and exclusively lock its
lockfile in read-only mode to accomodate package databases for which we
lack write permissions (e.g.  global package databases).

Instead, we now try read-write mode first, falling back to read-only
mode if this fails.

Reviewers: austin

Subscribers: rwbarton, thomie

GHC Trac Issues: #13945

Differential Revision: https://phabricator.haskell.org/D3897
parent 5f6a8204
......@@ -239,15 +239,21 @@ lockPackageDbWith mode file = do
-- DB for reading then we will require that the installer/packaging has
-- included the lock file.
--
-- Thus the logic here is to first try opening in read-only mode (to handle
-- global read-only DBs) and if the file does not exist then try opening in
-- read/write mode to create the lock file. If either succeed then lock the
-- file. IO exceptions (other than the first open attempt failing due to the
-- file not existing) simply propagate.
-- Thus the logic here is to first try opening in read-write mode
-- and if that fails we try read-only (to handle global read-only DBs).
-- If either succeed then lock the file. IO exceptions (other than the first
-- open attempt failing due to the file not existing) simply propagate.
--
-- Note that there is a complexity here which was discovered in #13945: some
-- filesystems (e.g. NFS) will only allow exclusive locking if the fd was
-- opened for write access. We would previously try opening the lockfile for
-- read-only access first, however this failed when run on such filesystems.
-- Consequently, we now try read-write access first, falling back to read-only
-- if are denied permission (e.g. in the case of a global database).
catchJust
(\e -> if isDoesNotExistError e then Just () else Nothing)
(lockFileOpenIn ReadMode)
(const $ lockFileOpenIn ReadWriteMode)
(\e -> if isPermissionError e then Just () else Nothing)
(lockFileOpenIn ReadWriteMode)
(const $ lockFileOpenIn ReadMode)
where
lock = file <.> "lock"
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment