{-# LANGUAGE CPP #-}
{-# LANGUAGE Trustworthy #-}
module System.Daemon (
#if !(defined(mingw32_HOST_OS) || defined(mingw32_TARGET_OS) || defined(__MINGW32__))
detachDaemon
#endif
)
where
#if !(defined(mingw32_HOST_OS) || defined(mingw32_TARGET_OS) || defined(__MINGW32__))
import System.Directory ( setCurrentDirectory )
import System.Exit ( ExitCode(ExitSuccess) )
import System.Log.Logger ( traplogging, Priority(ERROR) )
import System.Posix.IO
( openFd,
closeFd,
defaultFileFlags,
dupTo,
stdError,
stdInput,
stdOutput,
OpenMode(ReadWrite) )
import System.Posix.Process
( createSession, exitImmediately, forkProcess )
trap :: IO a -> IO a
trap :: forall a. IO a -> IO a
trap = String -> Priority -> String -> IO a -> IO a
forall a. String -> Priority -> String -> IO a -> IO a
traplogging String
"System.Daemon" Priority
ERROR String
"detachDaemon"
detachDaemon :: IO ()
detachDaemon :: IO ()
detachDaemon = IO () -> IO ()
forall a. IO a -> IO a
trap (IO () -> IO ()) -> IO () -> IO ()
forall a b. (a -> b) -> a -> b
$
do ProcessID
_ <- IO () -> IO ProcessID
forkProcess IO ()
child1
ExitCode -> IO ()
exitImmediately ExitCode
ExitSuccess
child1 :: IO ()
child1 :: IO ()
child1 = IO () -> IO ()
forall a. IO a -> IO a
trap (IO () -> IO ()) -> IO () -> IO ()
forall a b. (a -> b) -> a -> b
$
do ProcessID
_ <- IO ProcessID
createSession
ProcessID
_ <- IO () -> IO ProcessID
forkProcess IO ()
child2
ExitCode -> IO ()
exitImmediately ExitCode
ExitSuccess
child2 :: IO ()
child2 :: IO ()
child2 = IO () -> IO ()
forall a. IO a -> IO a
trap (IO () -> IO ()) -> IO () -> IO ()
forall a b. (a -> b) -> a -> b
$
do String -> IO ()
setCurrentDirectory String
"/"
(Fd -> IO ()) -> [Fd] -> IO ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
(a -> m b) -> t a -> m ()
mapM_ Fd -> IO ()
closeFd [Fd
stdInput, Fd
stdOutput, Fd
stdError]
Fd
nullFd <- String -> OpenMode -> Maybe FileMode -> OpenFileFlags -> IO Fd
openFd String
"/dev/null" OpenMode
ReadWrite Maybe FileMode
forall a. Maybe a
Nothing OpenFileFlags
defaultFileFlags
(Fd -> IO Fd) -> [Fd] -> IO ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
(a -> m b) -> t a -> m ()
mapM_ (Fd -> Fd -> IO Fd
dupTo Fd
nullFd) [Fd
stdInput, Fd
stdOutput, Fd
stdError]
Fd -> IO ()
closeFd Fd
nullFd
#endif