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:
Joey Hess 2014-08-20 11:25:07 -04:00
parent dfec2ffb22
commit 092041fab0
8 changed files with 23 additions and 3 deletions

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

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