Ensure that all lock fds are close-on-exec, fixing various problems with them being inherited by child processes such as git commands.
(With the exception of daemon pid locking.) This fixes at part of #758630. I reproduced the assistant locking eg, a removable drive's annex journal lock file and forking a long-running git-cat-file process that inherited that lock. This did not affect Windows. Considered doing a portable Utility.LockFile layer, but git-annex uses posix locks in several special ways that have no direct Windows equivilant, and it seems like it would mostly be a complication. This commit was sponsored by Protonet.
This commit is contained in:
parent
dfec2ffb22
commit
092041fab0
8 changed files with 23 additions and 3 deletions
|
@ -192,7 +192,9 @@ lockContent key a = do
|
|||
v <- tryIO $ setLock fd (WriteLock, AbsoluteSeek, 0, 0)
|
||||
case v of
|
||||
Left _ -> alreadylocked
|
||||
Right _ -> return $ Just fd
|
||||
Right _ -> do
|
||||
setFdOption fd CloseOnExec True
|
||||
return $ Just fd
|
||||
unlock mlockfile mfd = do
|
||||
maybe noop cleanuplockfile mlockfile
|
||||
liftIO $ maybe noop closeFd mfd
|
||||
|
|
|
@ -37,6 +37,7 @@ lockFileShared file = go =<< fromLockPool file
|
|||
mode <- annexFileMode
|
||||
lockhandle <- liftIO $ noUmask mode $
|
||||
openFd file ReadOnly (Just mode) defaultFileFlags
|
||||
setFdOption lockhandle CloseOnExec True
|
||||
liftIO $ waitToSetLock lockhandle (ReadLock, AbsoluteSeek, 0, 0)
|
||||
#else
|
||||
lockhandle <- liftIO $ waitToLock $ lockShared file
|
||||
|
@ -70,13 +71,19 @@ changeLockPool a = do
|
|||
withExclusiveLock :: (Git.Repo -> FilePath) -> Annex a -> Annex a
|
||||
withExclusiveLock getlockfile a = do
|
||||
lockfile <- fromRepo getlockfile
|
||||
liftIO $ hPutStrLn stderr (show ("locking", lockfile))
|
||||
liftIO $ hFlush stderr
|
||||
createAnnexDirectory $ takeDirectory lockfile
|
||||
mode <- annexFileMode
|
||||
bracketIO (lock lockfile mode) unlock (const a)
|
||||
r <- bracketIO (lock lockfile mode) unlock (const a)
|
||||
liftIO $ hPutStrLn stderr (show ("unlocked", lockfile))
|
||||
liftIO $ hFlush stderr
|
||||
return r
|
||||
where
|
||||
#ifndef mingw32_HOST_OS
|
||||
lock lockfile mode = do
|
||||
l <- noUmask mode $ createFile lockfile mode
|
||||
setFdOption l CloseOnExec True
|
||||
waitToSetLock l (WriteLock, AbsoluteSeek, 0, 0)
|
||||
return l
|
||||
unlock = closeFd
|
||||
|
|
|
@ -153,6 +153,7 @@ sshCleanup = mapM_ cleanup =<< enumSocketFiles
|
|||
mode <- annexFileMode
|
||||
fd <- liftIO $ noUmask mode $
|
||||
openFd lockfile ReadWrite (Just mode) defaultFileFlags
|
||||
setFdOption fd CloseOnExec True
|
||||
v <- liftIO $ tryIO $
|
||||
setLock fd (WriteLock, AbsoluteSeek, 0, 0)
|
||||
case v of
|
||||
|
|
|
@ -81,6 +81,7 @@ runTransfer' ignorelock t file shouldretry a = do
|
|||
case mfd of
|
||||
Nothing -> return (Nothing, False)
|
||||
Just fd -> do
|
||||
setFdOption fd CloseOnExec True
|
||||
locked <- catchMaybeIO $
|
||||
setLock fd (WriteLock, AbsoluteSeek, 0, 0)
|
||||
if isNothing locked
|
||||
|
|
|
@ -101,6 +101,7 @@ lockPreCommitHook a = do
|
|||
#ifndef mingw32_HOST_OS
|
||||
lock lockfile mode = do
|
||||
l <- liftIO $ noUmask mode $ createFile lockfile mode
|
||||
setFdOption l CloseOnExec True
|
||||
liftIO $ waitToSetLock l (WriteLock, AbsoluteSeek, 0, 0)
|
||||
return l
|
||||
unlock = closeFd
|
||||
|
|
|
@ -86,6 +86,7 @@ runHooks r starthook stophook a = do
|
|||
mode <- annexFileMode
|
||||
fd <- liftIO $ noUmask mode $
|
||||
openFd lck ReadWrite (Just mode) defaultFileFlags
|
||||
setFdOption fd CloseOnExec True
|
||||
v <- liftIO $ tryIO $
|
||||
setLock fd (WriteLock, AbsoluteSeek, 0, 0)
|
||||
case v of
|
||||
|
|
|
@ -44,15 +44,20 @@ lockExclusive = openLock fILE_SHARE_NONE
|
|||
- Note that createFile busy-waits to try to avoid failing when some other
|
||||
- process briefly has a file open. But that would make checking locks
|
||||
- much more expensive, so is not done here. Thus, the use of c_CreateFile.
|
||||
-
|
||||
- Also, passing Nothing for SECURITY_ATTRIBUTES ensures that the lock file
|
||||
- is not inheerited by any child process.
|
||||
-}
|
||||
openLock :: ShareMode -> LockFile -> IO (Maybe LockHandle)
|
||||
openLock sharemode f = do
|
||||
h <- withTString f $ \c_f ->
|
||||
c_CreateFile c_f gENERIC_READ sharemode (maybePtr Nothing)
|
||||
c_CreateFile c_f gENERIC_READ sharemode security_attributes
|
||||
oPEN_ALWAYS fILE_ATTRIBUTE_NORMAL (maybePtr Nothing)
|
||||
return $ if h == iNVALID_HANDLE_VALUE
|
||||
then Nothing
|
||||
else Just h
|
||||
where
|
||||
security_attributes = maybePtr Nothing
|
||||
|
||||
dropLock :: LockHandle -> IO ()
|
||||
dropLock = closeHandle
|
||||
|
|
2
debian/changelog
vendored
2
debian/changelog
vendored
|
@ -1,6 +1,8 @@
|
|||
git-annex (5.20140818) UNRELEASED; urgency=medium
|
||||
|
||||
* Make --help work when not in a git repository. Closes: #758592
|
||||
* Ensure that all lock fds are close-on-exec, fixing various problems with
|
||||
them being inherited by child processes such as git commands.
|
||||
|
||||
-- Joey Hess <joeyh@debian.org> Tue, 19 Aug 2014 12:52:41 -0400
|
||||
|
||||
|
|
Loading…
Reference in a new issue