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)
|
v <- tryIO $ setLock fd (WriteLock, AbsoluteSeek, 0, 0)
|
||||||
case v of
|
case v of
|
||||||
Left _ -> alreadylocked
|
Left _ -> alreadylocked
|
||||||
Right _ -> return $ Just fd
|
Right _ -> do
|
||||||
|
setFdOption fd CloseOnExec True
|
||||||
|
return $ Just fd
|
||||||
unlock mlockfile mfd = do
|
unlock mlockfile mfd = do
|
||||||
maybe noop cleanuplockfile mlockfile
|
maybe noop cleanuplockfile mlockfile
|
||||||
liftIO $ maybe noop closeFd mfd
|
liftIO $ maybe noop closeFd mfd
|
||||||
|
|
|
@ -37,6 +37,7 @@ lockFileShared file = go =<< fromLockPool file
|
||||||
mode <- annexFileMode
|
mode <- annexFileMode
|
||||||
lockhandle <- liftIO $ noUmask mode $
|
lockhandle <- liftIO $ noUmask mode $
|
||||||
openFd file ReadOnly (Just mode) defaultFileFlags
|
openFd file ReadOnly (Just mode) defaultFileFlags
|
||||||
|
setFdOption lockhandle CloseOnExec True
|
||||||
liftIO $ waitToSetLock lockhandle (ReadLock, AbsoluteSeek, 0, 0)
|
liftIO $ waitToSetLock lockhandle (ReadLock, AbsoluteSeek, 0, 0)
|
||||||
#else
|
#else
|
||||||
lockhandle <- liftIO $ waitToLock $ lockShared file
|
lockhandle <- liftIO $ waitToLock $ lockShared file
|
||||||
|
@ -70,13 +71,19 @@ changeLockPool a = do
|
||||||
withExclusiveLock :: (Git.Repo -> FilePath) -> Annex a -> Annex a
|
withExclusiveLock :: (Git.Repo -> FilePath) -> Annex a -> Annex a
|
||||||
withExclusiveLock getlockfile a = do
|
withExclusiveLock getlockfile a = do
|
||||||
lockfile <- fromRepo getlockfile
|
lockfile <- fromRepo getlockfile
|
||||||
|
liftIO $ hPutStrLn stderr (show ("locking", lockfile))
|
||||||
|
liftIO $ hFlush stderr
|
||||||
createAnnexDirectory $ takeDirectory lockfile
|
createAnnexDirectory $ takeDirectory lockfile
|
||||||
mode <- annexFileMode
|
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
|
where
|
||||||
#ifndef mingw32_HOST_OS
|
#ifndef mingw32_HOST_OS
|
||||||
lock lockfile mode = do
|
lock lockfile mode = do
|
||||||
l <- noUmask mode $ createFile lockfile mode
|
l <- noUmask mode $ createFile lockfile mode
|
||||||
|
setFdOption l CloseOnExec True
|
||||||
waitToSetLock l (WriteLock, AbsoluteSeek, 0, 0)
|
waitToSetLock l (WriteLock, AbsoluteSeek, 0, 0)
|
||||||
return l
|
return l
|
||||||
unlock = closeFd
|
unlock = closeFd
|
||||||
|
|
|
@ -153,6 +153,7 @@ sshCleanup = mapM_ cleanup =<< enumSocketFiles
|
||||||
mode <- annexFileMode
|
mode <- annexFileMode
|
||||||
fd <- liftIO $ noUmask mode $
|
fd <- liftIO $ noUmask mode $
|
||||||
openFd lockfile ReadWrite (Just mode) defaultFileFlags
|
openFd lockfile ReadWrite (Just mode) defaultFileFlags
|
||||||
|
setFdOption fd CloseOnExec True
|
||||||
v <- liftIO $ tryIO $
|
v <- liftIO $ tryIO $
|
||||||
setLock fd (WriteLock, AbsoluteSeek, 0, 0)
|
setLock fd (WriteLock, AbsoluteSeek, 0, 0)
|
||||||
case v of
|
case v of
|
||||||
|
|
|
@ -81,6 +81,7 @@ runTransfer' ignorelock t file shouldretry a = do
|
||||||
case mfd of
|
case mfd of
|
||||||
Nothing -> return (Nothing, False)
|
Nothing -> return (Nothing, False)
|
||||||
Just fd -> do
|
Just fd -> do
|
||||||
|
setFdOption fd CloseOnExec True
|
||||||
locked <- catchMaybeIO $
|
locked <- catchMaybeIO $
|
||||||
setLock fd (WriteLock, AbsoluteSeek, 0, 0)
|
setLock fd (WriteLock, AbsoluteSeek, 0, 0)
|
||||||
if isNothing locked
|
if isNothing locked
|
||||||
|
|
|
@ -101,6 +101,7 @@ lockPreCommitHook a = do
|
||||||
#ifndef mingw32_HOST_OS
|
#ifndef mingw32_HOST_OS
|
||||||
lock lockfile mode = do
|
lock lockfile mode = do
|
||||||
l <- liftIO $ noUmask mode $ createFile lockfile mode
|
l <- liftIO $ noUmask mode $ createFile lockfile mode
|
||||||
|
setFdOption l CloseOnExec True
|
||||||
liftIO $ waitToSetLock l (WriteLock, AbsoluteSeek, 0, 0)
|
liftIO $ waitToSetLock l (WriteLock, AbsoluteSeek, 0, 0)
|
||||||
return l
|
return l
|
||||||
unlock = closeFd
|
unlock = closeFd
|
||||||
|
|
|
@ -86,6 +86,7 @@ runHooks r starthook stophook a = do
|
||||||
mode <- annexFileMode
|
mode <- annexFileMode
|
||||||
fd <- liftIO $ noUmask mode $
|
fd <- liftIO $ noUmask mode $
|
||||||
openFd lck ReadWrite (Just mode) defaultFileFlags
|
openFd lck ReadWrite (Just mode) defaultFileFlags
|
||||||
|
setFdOption fd CloseOnExec True
|
||||||
v <- liftIO $ tryIO $
|
v <- liftIO $ tryIO $
|
||||||
setLock fd (WriteLock, AbsoluteSeek, 0, 0)
|
setLock fd (WriteLock, AbsoluteSeek, 0, 0)
|
||||||
case v of
|
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
|
- 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
|
- 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.
|
- 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 -> LockFile -> IO (Maybe LockHandle)
|
||||||
openLock sharemode f = do
|
openLock sharemode f = do
|
||||||
h <- withTString f $ \c_f ->
|
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)
|
oPEN_ALWAYS fILE_ATTRIBUTE_NORMAL (maybePtr Nothing)
|
||||||
return $ if h == iNVALID_HANDLE_VALUE
|
return $ if h == iNVALID_HANDLE_VALUE
|
||||||
then Nothing
|
then Nothing
|
||||||
else Just h
|
else Just h
|
||||||
|
where
|
||||||
|
security_attributes = maybePtr Nothing
|
||||||
|
|
||||||
dropLock :: LockHandle -> IO ()
|
dropLock :: LockHandle -> IO ()
|
||||||
dropLock = closeHandle
|
dropLock = closeHandle
|
||||||
|
|
2
debian/changelog
vendored
2
debian/changelog
vendored
|
@ -1,6 +1,8 @@
|
||||||
git-annex (5.20140818) UNRELEASED; urgency=medium
|
git-annex (5.20140818) UNRELEASED; urgency=medium
|
||||||
|
|
||||||
* Make --help work when not in a git repository. Closes: #758592
|
* 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
|
-- Joey Hess <joeyh@debian.org> Tue, 19 Aug 2014 12:52:41 -0400
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue