diff options
author | Joey Hess <joeyh@joeyh.name> | 2015-02-17 13:04:22 -0400 |
---|---|---|
committer | Joey Hess <joeyh@joeyh.name> | 2015-02-17 13:30:24 -0400 |
commit | c18aca6a6a1673d17467e25eb5c900f824c8231c (patch) | |
tree | 0ef32f822433fc6a6306db0b31640588224e19e8 /Annex | |
parent | d14b4c2a607409fbec81fedd2cc89ee77ba6a62e (diff) |
avoid crash when starting fsck --incremental when one is already running
Turns out sqlite does not like having its database deleted out from
underneath it. It might suffice to empty the table, but I would rather
start each fsck over with a new database, so I added a lock file, and
running incremental fscks use a shared lock.
This leaves one concurrency bug left; running two concurrent fsck --more
will lead to: "SQLite3 returned ErrorBusy while attempting to perform step."
and one or both will fail. This is a concurrent writers problem.
Diffstat (limited to 'Annex')
-rw-r--r-- | Annex/LockFile.hs | 21 |
1 files changed, 20 insertions, 1 deletions
diff --git a/Annex/LockFile.hs b/Annex/LockFile.hs index 18e876c75..62a101aa5 100644 --- a/Annex/LockFile.hs +++ b/Annex/LockFile.hs @@ -1,6 +1,6 @@ {- git-annex lock files. - - - Copyright 2012, 2014 Joey Hess <id@joeyh.name> + - Copyright 2012-2015 Joey Hess <id@joeyh.name> - - Licensed under the GNU GPL version 3 or higher. -} @@ -12,6 +12,7 @@ module Annex.LockFile ( unlockFile, getLockPool, withExclusiveLock, + tryExclusiveLock, ) where import Common.Annex @@ -70,3 +71,21 @@ withExclusiveLock getlockfile a = do #else lock _mode = waitToLock . lockExclusive #endif + +{- Tries to take an exclusive lock and run an action. If the lock is + - already held, returns Nothing. -} +tryExclusiveLock :: (Git.Repo -> FilePath) -> Annex a -> Annex (Maybe a) +tryExclusiveLock getlockfile a = do + lockfile <- fromRepo getlockfile + createAnnexDirectory $ takeDirectory lockfile + mode <- annexFileMode + bracketIO (lock mode lockfile) unlock go + where +#ifndef mingw32_HOST_OS + lock mode = noUmask mode . tryLockExclusive (Just mode) +#else + lock _mode = lockExclusive +#endif + unlock = maybe noop dropLock + go Nothing = return Nothing + go (Just _) = Just <$> a |