fixed a fd double-close
This commit is contained in:
parent
b0155d9093
commit
389c6c7d37
1 changed files with 20 additions and 27 deletions
|
@ -39,7 +39,7 @@ import System.Directory
|
||||||
|
|
||||||
type LockFile = FilePath
|
type LockFile = FilePath
|
||||||
|
|
||||||
data LockHandle = LockHandle FilePath Fd SideLockHandle
|
data LockHandle = LockHandle FilePath FileStatus SideLockHandle
|
||||||
|
|
||||||
type SideLockHandle = Maybe Posix.LockHandle
|
type SideLockHandle = Maybe Posix.LockHandle
|
||||||
|
|
||||||
|
@ -100,17 +100,17 @@ tryLock lockfile = trySideLock lockfile $ \sidelock -> do
|
||||||
setFileMode tmp (combineModes readModes)
|
setFileMode tmp (combineModes readModes)
|
||||||
hPutStr h . show =<< mkPidLock
|
hPutStr h . show =<< mkPidLock
|
||||||
hClose h
|
hClose h
|
||||||
|
st <- getFileStatus tmp
|
||||||
let failedlock = do
|
let failedlock = do
|
||||||
nukeFile tmp
|
nukeFile tmp
|
||||||
maybe noop Posix.dropLock sidelock
|
maybe noop Posix.dropLock sidelock
|
||||||
return Nothing
|
return Nothing
|
||||||
let tooklock fd = return $ Just $ LockHandle lockfile fd sidelock
|
let tooklock = return $ Just $ LockHandle lockfile st sidelock
|
||||||
mfd <- linkToLock sidelock tmp lockfile
|
ifM (linkToLock sidelock tmp lockfile)
|
||||||
case mfd of
|
( do
|
||||||
Just fd -> do
|
|
||||||
nukeFile tmp
|
nukeFile tmp
|
||||||
tooklock fd
|
tooklock
|
||||||
Nothing -> do
|
, do
|
||||||
v <- readPidLock lockfile
|
v <- readPidLock lockfile
|
||||||
hn <- getHostName
|
hn <- getHostName
|
||||||
case v of
|
case v of
|
||||||
|
@ -121,9 +121,9 @@ tryLock lockfile = trySideLock lockfile $ \sidelock -> do
|
||||||
-- we know that the pidlock is
|
-- we know that the pidlock is
|
||||||
-- stale, and can take it over.
|
-- stale, and can take it over.
|
||||||
rename tmp lockfile
|
rename tmp lockfile
|
||||||
fd <- openFd lockfile ReadOnly Nothing defaultFileFlags
|
tooklock
|
||||||
tooklock fd
|
|
||||||
_ -> failedlock
|
_ -> failedlock
|
||||||
|
)
|
||||||
|
|
||||||
-- Linux's open(2) man page recommends linking a pid lock into place,
|
-- Linux's open(2) man page recommends linking a pid lock into place,
|
||||||
-- as the most portable atomic operation that will fail if
|
-- as the most portable atomic operation that will fail if
|
||||||
|
@ -141,21 +141,16 @@ tryLock lockfile = trySideLock lockfile $ \sidelock -> do
|
||||||
-- can't do anything about such a lying filesystem.
|
-- can't do anything about such a lying filesystem.
|
||||||
-- At least the side lock file will prevent git-annex's running on the same
|
-- At least the side lock file will prevent git-annex's running on the same
|
||||||
-- host from running concurrently even on such a lying filesystem.
|
-- host from running concurrently even on such a lying filesystem.
|
||||||
linkToLock :: SideLockHandle -> FilePath -> FilePath -> IO (Maybe Fd)
|
linkToLock :: SideLockHandle -> FilePath -> FilePath -> IO Bool
|
||||||
linkToLock Nothing _ _ = return Nothing
|
linkToLock Nothing _ _ = return False
|
||||||
linkToLock (Just _) src dest = do
|
linkToLock (Just _) src dest = do
|
||||||
_ <- tryIO $ createLink src dest
|
_ <- tryIO $ createLink src dest
|
||||||
ifM (catchDefaultIO False checklink)
|
ifM (catchBoolIO checklink)
|
||||||
( catchDefaultIO Nothing $ do
|
( catchBoolIO $ do
|
||||||
srccontent <- readFile src
|
srccontent <- readFile src
|
||||||
h <- openFile dest ReadMode
|
destcontent <- readFile dest
|
||||||
destcontent <- hGetContents h
|
return (srccontent == destcontent)
|
||||||
if srccontent /= destcontent
|
, return False
|
||||||
then do
|
|
||||||
hClose h
|
|
||||||
return Nothing
|
|
||||||
else Just <$> handleToFd h
|
|
||||||
, return Nothing
|
|
||||||
)
|
)
|
||||||
where
|
where
|
||||||
checklink = do
|
checklink = do
|
||||||
|
@ -192,13 +187,12 @@ waitLock (Seconds timeout) lockfile = go timeout
|
||||||
error $ "Gave up waiting for possibly stale pid lock file " ++ lockfile
|
error $ "Gave up waiting for possibly stale pid lock file " ++ lockfile
|
||||||
|
|
||||||
dropLock :: LockHandle -> IO ()
|
dropLock :: LockHandle -> IO ()
|
||||||
dropLock (LockHandle lockfile fd sidelock) = do
|
dropLock (LockHandle lockfile _ sidelock) = do
|
||||||
-- Drop side lock first, at which point the pid lock will be
|
-- Drop side lock first, at which point the pid lock will be
|
||||||
-- considered stale.
|
-- considered stale.
|
||||||
-- The side lock file cannot be deleted because another process may
|
-- The side lock file cannot be deleted because another process may
|
||||||
-- have it open and be waiting to lock it.
|
-- have it open and be waiting to lock it.
|
||||||
maybe noop Posix.dropLock sidelock
|
maybe noop Posix.dropLock sidelock
|
||||||
closeFd fd
|
|
||||||
nukeFile lockfile
|
nukeFile lockfile
|
||||||
|
|
||||||
getLockStatus :: LockFile -> IO LockStatus
|
getLockStatus :: LockFile -> IO LockStatus
|
||||||
|
@ -213,10 +207,9 @@ checkLocked lockfile = conv <$> getLockStatus lockfile
|
||||||
-- Checks that the lock file still exists, and is the same file that was
|
-- Checks that the lock file still exists, and is the same file that was
|
||||||
-- locked to get the LockHandle.
|
-- locked to get the LockHandle.
|
||||||
checkSaneLock :: LockFile -> LockHandle -> IO Bool
|
checkSaneLock :: LockFile -> LockHandle -> IO Bool
|
||||||
checkSaneLock lockfile (LockHandle _ fd _) =
|
checkSaneLock lockfile (LockHandle _ st _) =
|
||||||
go =<< catchMaybeIO (getFileStatus lockfile)
|
go =<< catchMaybeIO (getFileStatus lockfile)
|
||||||
where
|
where
|
||||||
go Nothing = return False
|
go Nothing = return False
|
||||||
go (Just st) = do
|
go (Just st') = do
|
||||||
fdst <- getFdStatus fd
|
return $ deviceID st == deviceID st' && fileID st == fileID st'
|
||||||
return $ deviceID fdst == deviceID st && fileID fdst == fileID st
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue