shellmate-0.3.3: Control/Shell/Daemon.hs
-- | Daemonize a shellmate computation.
-- Not present on Windows, unless shellmate is installed with the
-- @with-posix@ flag.
module Control.Shell.Daemon (daemonize) where
import Control.Shell hiding (stdin)
import System.Directory
import System.Exit
import System.IO
import System.Posix
-- | Daemonize a shellmate computation. This should be the last thing a
-- computation does, as this function will terminate the parent computation.
-- In short, daemonizing a computation involves setting the file creation
-- mask to 0, closing standard input, output and error file descriptors,
-- blocking sighup and changing the working directory to @/@.
--
-- On Windows without Cygwin, @daemonize@ is a no-op. Consider running any
-- program intended to be deamonized using @START /B your_app@, or better yet,
-- rewriting it as a Windows service.
daemonize :: Shell () -> Shell ()
daemonize m = do
env <- getShellEnv
unsafeLiftIO $ do
void $ setFileCreationMask 0
void $ forkProcess (p env)
exitImmediately ExitSuccess
where
p env = do
void $ createSession
void $ forkProcess (p' env)
exitImmediately ExitSuccess
p' env = do
changeWorkingDirectory "/"
devnull <- openFd "/dev/null" ReadWrite Nothing defaultFileFlags
mapM_ closeFd [stdInput, stdOutput, stdError]
mapM_ (dupTo devnull) [stdInput, stdOutput, stdError]
void $ installHandler sigHUP Ignore Nothing
dir <- getCurrentDirectory
res <- flip runSh m $ env
{ envStdIn = stdin
, envStdOut = stdout
, envStdErr = stderr
, envWorkDir = dir
, envEnvVars = envEnvVars env
}
case res of
Left (Failure _) -> exitFailure
_ -> exitSuccess