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.
This commit is contained in:
Joey Hess 2015-02-17 13:04:22 -04:00
parent ea76d04e15
commit afb3e3e472
4 changed files with 50 additions and 8 deletions

View file

@ -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