diff options
author | 2015-05-18 14:16:49 -0400 | |
---|---|---|
committer | 2015-05-18 15:57:17 -0400 | |
commit | 94a3e606fb31150c969d63790ec1ef870f413cc1 (patch) | |
tree | 566860a856e7d064e18de4c3a8a2e561377caf3c /Utility/LockPool/Posix.hs | |
parent | 6a318cf0c050f9fa7959874bf0eb8f1105ef0a4b (diff) |
lock pools to work around non-concurrency/composition safety of POSIX fcntl
Diffstat (limited to 'Utility/LockPool/Posix.hs')
-rw-r--r-- | Utility/LockPool/Posix.hs | 59 |
1 files changed, 59 insertions, 0 deletions
diff --git a/Utility/LockPool/Posix.hs b/Utility/LockPool/Posix.hs new file mode 100644 index 000000000..e460272f2 --- /dev/null +++ b/Utility/LockPool/Posix.hs @@ -0,0 +1,59 @@ +{- Posix lock files, using lock pools. + - + - Copyright 2015 Joey Hess <id@joeyh.name> + - + - License: BSD-2-clause + -} + +module Utility.LockPool.Posix ( + LockHandle, + lockShared, + lockExclusive, + tryLockExclusive, + checkLocked, + getLockStatus, + dropLock, + checkSaneLock, +) where + +import qualified Utility.LockFile.Posix as F +import qualified Utility.LockPool.STM as P +import Utility.LockPool.STM (LockPool, LockFile, LockMode(..)) +import Utility.LockPool.LockHandle +import Utility.Monad + +import Control.Concurrent.STM +import System.IO +import System.Posix +import Data.Maybe +import Control.Applicative +import Prelude + +-- Takes a shared lock, blocking until the lock is available. +lockShared :: Maybe FileMode -> LockFile -> IO LockHandle +lockShared mode file = makeLockHandle + (P.waitTakeLock P.lockPool file LockShared) + (F.lockShared mode file) + +lockExclusive :: Maybe FileMode -> LockFile -> IO LockHandle +lockExclusive mode file = makeLockHandle + (P.waitTakeLock P.lockPool file LockExclusive) + (F.lockExclusive mode file) + +tryLockExclusive :: Maybe FileMode -> LockFile -> IO (Maybe LockHandle) +tryLockExclusive mode file = tryMakeLockHandle + (P.tryTakeLock P.lockPool file LockExclusive) + (F.tryLockExclusive mode file) + +-- Returns Nothing when the file doesn't exist, for cases where +-- that is different from it not being locked. +checkLocked :: LockFile -> IO (Maybe Bool) +checkLocked file = P.getLockStatus P.lockPool file (pure True) + (F.checkLocked file) + +getLockStatus :: LockFile -> IO (Maybe ProcessID) +getLockStatus file = P.getLockStatus P.lockPool file getProcessID + (F.getLockStatus file) + +checkSaneLock :: LockFile -> LockHandle -> IO Bool +checkSaneLock lockfile (LockHandle _ fh) = F.checkSaneLock lockfile fh |