summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CmdLine.hs1
-rw-r--r--Command.hs8
-rw-r--r--Command/Log.hs2
-rw-r--r--Git/Command.hs12
-rw-r--r--Utility/Misc.hs14
-rw-r--r--Utility/Rsync.hs9
6 files changed, 25 insertions, 21 deletions
diff --git a/CmdLine.hs b/CmdLine.hs
index 331c363e4..66bf5b882 100644
--- a/CmdLine.hs
+++ b/CmdLine.hs
@@ -117,5 +117,6 @@ shutdown :: Bool -> Annex Bool
shutdown nocommit = do
saveState nocommit
sequence_ =<< M.elems <$> Annex.getState Annex.cleanup
+ liftIO reapZombies -- zombies from long-running git processes
sshCleanup -- ssh connection caching
return True
diff --git a/Command.hs b/Command.hs
index 145ad5003..8e7bf9758 100644
--- a/Command.hs
+++ b/Command.hs
@@ -39,7 +39,6 @@ import Usage as ReExported
import Logs.Trust
import Config
import Annex.CheckAttr
-import qualified Git.Command
{- Generates a normal command -}
command :: String -> String -> [CommandSeek] -> String -> Command
@@ -84,14 +83,11 @@ doCommand = start
where
start = stage $ maybe skip perform
perform = stage $ maybe failure cleanup
- cleanup = stage $ end
+ cleanup = stage $ status
stage = (=<<)
skip = return True
failure = showEndFail >> return False
- end r = do
- -- zombies from long-running git processes
- liftIO Git.Command.reap
- showEndResult r >> return r
+ status r = showEndResult r >> return r
{- Modifies an action to only act on files that are already annexed,
- and passes the key and backend on to it. -}
diff --git a/Command/Log.hs b/Command/Log.hs
index c3ce67986..09d22b2ef 100644
--- a/Command/Log.hs
+++ b/Command/Log.hs
@@ -70,7 +70,7 @@ start :: M.Map UUID String -> TimeZone -> [CommandParam] -> Bool ->
start m zone os gource file (key, _) = do
showLog output =<< readLog <$> getLog key os
-- getLog produces a zombie; reap it
- liftIO Git.Command.reap
+ liftIO reapZombies
stop
where
output
diff --git a/Git/Command.hs b/Git/Command.hs
index 5f2dd47b0..37df44713 100644
--- a/Git/Command.hs
+++ b/Git/Command.hs
@@ -7,7 +7,6 @@
module Git.Command where
-import System.Posix.Process (getAnyProcessStatus)
import System.Process (std_out, env)
import Common
@@ -97,17 +96,6 @@ pipeNullSplitZombie params repo = leaveZombie <$> pipeNullSplit params repo
leaveZombie :: (a, IO Bool) -> a
leaveZombie = fst
-{- Reaps any zombie git processes.
- -
- - Warning: Not thread safe. Anything that was expecting to wait
- - on a process and get back an exit status is going to be confused
- - if this reap gets there first. -}
-reap :: IO ()
-reap = do
- -- throws an exception when there are no child processes
- catchDefaultIO Nothing (getAnyProcessStatus False True)
- >>= maybe noop (const reap)
-
{- Runs a git command as a coprocess. -}
gitCoProcessStart :: [CommandParam] -> Repo -> IO CoProcess.CoProcessHandle
gitCoProcessStart params repo = CoProcess.start "git" (toCommand $ gitCommandLine params repo) (gitEnv repo)
diff --git a/Utility/Misc.hs b/Utility/Misc.hs
index f03504040..7c81f56fd 100644
--- a/Utility/Misc.hs
+++ b/Utility/Misc.hs
@@ -12,6 +12,9 @@ import Control.Monad
import Foreign
import Data.Char
import Control.Applicative
+import System.Posix.Process (getAnyProcessStatus)
+
+import Utility.Exception
{- A version of hgetContents that is not lazy. Ensures file is
- all read before it gets closed. -}
@@ -96,3 +99,14 @@ hGetSomeString h sz = do
where
peekbytes :: Int -> Ptr Word8 -> IO [Word8]
peekbytes len buf = mapM (peekElemOff buf) [0..pred len]
+
+{- Reaps any zombie git processes.
+ -
+ - Warning: Not thread safe. Anything that was expecting to wait
+ - on a process and get back an exit status is going to be confused
+ - if this reap gets there first. -}
+reapZombies :: IO ()
+reapZombies = do
+ -- throws an exception when there are no child processes
+ catchDefaultIO Nothing (getAnyProcessStatus False True)
+ >>= maybe (return ()) (const reapZombies)
diff --git a/Utility/Rsync.hs b/Utility/Rsync.hs
index f8e19eb57..68d27550c 100644
--- a/Utility/Rsync.hs
+++ b/Utility/Rsync.hs
@@ -53,8 +53,13 @@ rsync = boolSystem "rsync"
- The params must enable rsync's --progress mode for this to work.
-}
rsyncProgress :: (Integer -> IO ()) -> [CommandParam] -> IO Bool
-rsyncProgress callback params =
- withHandle StdoutHandle createProcessSuccess p (feedprogress 0 [])
+rsyncProgress callback params = do
+ r <- withHandle StdoutHandle createProcessSuccess p (feedprogress 0 [])
+ {- For an unknown reason, piping rsync's output like this does
+ - causes it to run a second ssh process, which it neglects to wait
+ - on. Reap the resulting zombie. -}
+ reapZombies
+ return r
where
p = proc "rsync" (toCommand params)
feedprogress prev buf h = do