convert to withCreateProcess for async exception safety

This handles all sites where checkSuccessProcess/ignoreFailureProcess
is used, except for one: Git.Command.pipeReadLazy
That one will be significantly more work to convert to bracketing.

(Also skipped Command.Assistant.autoStart, but it does not need to
shut down the processes it started on exception because they are
git-annex assistant daemons..)

forceSuccessProcess is done, except for createProcessSuccess.
All call sites of createProcessSuccess will need to be converted
to bracketing.

(process pools still todo also)
This commit is contained in:
Joey Hess 2020-06-04 12:13:26 -04:00
parent 2dc7b5186a
commit 438dbe3b66
No known key found for this signature in database
GPG key ID: DB12DB0FF05F8F38
13 changed files with 125 additions and 87 deletions

View file

@ -171,16 +171,19 @@ pipeLazy (GpgCmd cmd) params feeder reader = do
, std_out = CreatePipe
, std_err = Inherit
}
bracket (setup p) (cleanup p) go
bracket (setup p) cleanup (go p)
where
setup = liftIO . createProcess
cleanup p (_, _, _, pid) = liftIO $ forceSuccessProcess p pid
go p = do
let (to, from) = ioHandles p
cleanup = liftIO . cleanupProcess
go p (Just to, Just from, _, pid) = do
liftIO $ void $ forkIO $ do
feeder to
hClose to
reader from
r <- reader from
liftIO $ forceSuccessProcess p pid
return r
go _ _ = error "internal"
{- Finds gpg public keys matching some string. (Could be an email address,
- a key id, or a name; See the section 'HOW TO SPECIFY A USER ID' of

View file

@ -49,11 +49,16 @@ queryDir path = query ["+d", path]
- Note: If lsof is not available, this always returns [] !
-}
query :: [String] -> IO [(FilePath, LsofOpenMode, ProcessInfo)]
query opts =
withHandle StdoutHandle (createProcessChecked checkSuccessProcess) p $
parse <$$> hGetContentsStrict
query opts = withCreateProcess p go
where
p = proc "lsof" ("-F0can" : opts)
p = (proc "lsof" ("-F0can" : opts))
{ std_out = CreatePipe }
go _ (Just outh) _ pid = do
r <- parse <$> hGetContentsStrict outh
void $ waitForProcess pid
return r
go _ _ _ _ = error "internal"
type LsofParser = String -> [(FilePath, LsofOpenMode, ProcessInfo)]

View file

@ -20,7 +20,6 @@ module Utility.Process (
forceSuccessProcess,
forceSuccessProcess',
checkSuccessProcess,
ignoreFailureProcess,
createProcessSuccess,
createProcessChecked,
createBackgroundProcess,
@ -53,7 +52,6 @@ import System.Log.Logger
import Control.Monad.IO.Class
import Control.Concurrent
import qualified Control.Exception as E
import Control.Monad
import qualified Data.ByteString as S
type CreateProcessRunner = forall a. CreateProcess -> ((Maybe Handle, Maybe Handle, Maybe Handle, ProcessHandle) -> IO a) -> IO a
@ -135,11 +133,6 @@ checkSuccessProcess pid = do
code <- waitForProcess pid
return $ code == ExitSuccess
ignoreFailureProcess :: ProcessHandle -> IO Bool
ignoreFailureProcess pid = do
void $ waitForProcess pid
return True
-- | Runs createProcess, then an action on its handles, and then
-- forceSuccessProcess.
createProcessSuccess :: CreateProcessRunner