keter/Keter/Process.hs

60 lines
2.1 KiB
Haskell
Raw Normal View History

2012-05-14 11:15:50 +04:00
{-# LANGUAGE NoImplicitPrelude #-}
2012-05-06 14:28:18 +04:00
module Keter.Process
( run
, terminate
, Process
) where
2012-05-14 11:15:50 +04:00
import Keter.Prelude
2012-05-06 14:28:18 +04:00
import qualified System.Process as SP
data Status = NeedsRestart | NoRestart | Running SP.ProcessHandle
-- | Run the given command, restarting if the process dies.
run :: FilePath -- ^ executable
-> FilePath -- ^ working directory
-> [String] -- ^ command line parameter
-> [(String, String)] -- ^ environment
2012-05-14 12:03:57 +04:00
-> KIO Process
2012-05-06 14:28:18 +04:00
run exec dir args env = do
2012-05-14 12:03:57 +04:00
mstatus <- newMVar NeedsRestart
2012-05-06 14:28:18 +04:00
let loop = do
2012-05-14 12:03:57 +04:00
next <- modifyMVar mstatus $ \status ->
2012-05-06 14:28:18 +04:00
case status of
NoRestart -> return (NoRestart, return ())
_ -> do
2012-05-11 12:42:56 +04:00
-- FIXME put in some kind of rate limiting: if we last
-- tried to restart within five second, wait an extra
-- five seconds
2012-05-14 12:03:57 +04:00
res <- liftIO $ SP.createProcess cp
case res of
Left e -> do
log $ ExceptionThrown e
return (NeedsRestart, return ())
Right (_, _, _, ph) -> do
log $ ProcessCreated exec
return (Running ph, liftIO (SP.waitForProcess ph) >> loop)
2012-05-06 14:28:18 +04:00
next
2012-05-14 12:03:57 +04:00
forkKIO loop
2012-05-06 14:28:18 +04:00
return $ Process mstatus
where
2012-05-14 11:15:50 +04:00
cp = (SP.proc (toString exec) $ map toString args)
{ SP.cwd = Just $ toString dir
, SP.env = Just $ map (toString *** toString) env
2012-05-06 14:28:18 +04:00
, SP.std_in = SP.Inherit -- FIXME
, SP.std_out = SP.Inherit -- FIXME
, SP.std_err = SP.Inherit -- FIXME
, SP.close_fds = True
}
-- | Abstract type containing information on a process which will be restarted.
2012-05-14 12:03:57 +04:00
newtype Process = Process (MVar Status)
2012-05-06 14:28:18 +04:00
-- | Terminate the process and prevent it from being restarted.
2012-05-14 12:03:57 +04:00
terminate :: Process -> KIO ()
2012-05-06 14:28:18 +04:00
terminate (Process mstatus) = do
2012-05-14 12:03:57 +04:00
status <- swapMVar mstatus NoRestart
2012-05-06 14:28:18 +04:00
case status of
2012-05-14 12:03:57 +04:00
Running ph -> void $ liftIO $ SP.terminateProcess ph
2012-05-06 14:28:18 +04:00
_ -> return ()