{-# LINE 1 "System/Posix/Process/Common.hsc" #-}
{-# LANGUAGE CApiFFI #-}
{-# LANGUAGE InterruptibleFFI, RankNTypes #-}
{-# LANGUAGE Trustworthy #-}
module System.Posix.Process.Common (
forkProcess,
forkProcessWithUnmask,
exitImmediately,
getProcessID,
getParentProcessID,
getProcessGroupID,
getProcessGroupIDOf,
createProcessGroupFor,
joinProcessGroup,
setProcessGroupIDOf,
createSession,
ProcessTimes(..),
getProcessTimes,
clocksPerSec,
nice,
getProcessPriority,
getProcessGroupPriority,
getUserPriority,
setProcessPriority,
setProcessGroupPriority,
setUserPriority,
ProcessStatus(..),
getProcessStatus,
getAnyProcessStatus,
getGroupProcessStatus,
createProcessGroup,
setProcessGroupID,
) where
import Foreign.C.Error
import Foreign.C.Types
import Foreign.Marshal.Alloc ( alloca, allocaBytes )
import Foreign.Ptr ( Ptr )
import Foreign.StablePtr ( StablePtr, newStablePtr, freeStablePtr )
import Foreign.Storable ( Storable(..) )
import System.Exit
import System.Posix.Process.Internals
import System.Posix.Types
import Control.Monad
import Control.Exception.Base ( bracket, getMaskingState, MaskingState(..) )
import GHC.TopHandler ( runIO )
{-# LINE 87 "System/Posix/Process/Common.hsc" #-}
import GHC.IO ( unsafeUnmask, uninterruptibleMask_ )
{-# LINE 92 "System/Posix/Process/Common.hsc" #-}
{-# LINE 101 "System/Posix/Process/Common.hsc" #-}
getProcessID :: IO ProcessID
getProcessID = c_getpid
foreign import ccall unsafe "getpid"
c_getpid :: IO CPid
{-# LINE 113 "System/Posix/Process/Common.hsc" #-}
{-# LINE 122 "System/Posix/Process/Common.hsc" #-}
getParentProcessID :: IO ProcessID
getParentProcessID = c_getppid
foreign import ccall unsafe "getppid"
c_getppid :: IO CPid
{-# LINE 132 "System/Posix/Process/Common.hsc" #-}
{-# LINE 141 "System/Posix/Process/Common.hsc" #-}
getProcessGroupID :: IO ProcessGroupID
getProcessGroupID = c_getpgrp
foreign import ccall unsafe "getpgrp"
c_getpgrp :: IO CPid
{-# LINE 151 "System/Posix/Process/Common.hsc" #-}
{-# LINE 160 "System/Posix/Process/Common.hsc" #-}
getProcessGroupIDOf :: ProcessID -> IO ProcessGroupID
getProcessGroupIDOf pid =
throwErrnoIfMinus1 "getProcessGroupIDOf" (c_getpgid pid)
foreign import ccall unsafe "getpgid"
c_getpgid :: CPid -> IO CPid
{-# LINE 171 "System/Posix/Process/Common.hsc" #-}
{-# LINE 193 "System/Posix/Process/Common.hsc" #-}
createProcessGroupFor :: ProcessID -> IO ProcessGroupID
createProcessGroupFor pid = do
throwErrnoIfMinus1_ "createProcessGroupFor" (c_setpgid pid 0)
return pid
{-# LINE 202 "System/Posix/Process/Common.hsc" #-}
{-# LINE 211 "System/Posix/Process/Common.hsc" #-}
joinProcessGroup :: ProcessGroupID -> IO ()
joinProcessGroup pgid =
throwErrnoIfMinus1_ "joinProcessGroup" (c_setpgid 0 pgid)
{-# LINE 219 "System/Posix/Process/Common.hsc" #-}
{-# LINE 239 "System/Posix/Process/Common.hsc" #-}
setProcessGroupIDOf :: ProcessID -> ProcessGroupID -> IO ()
setProcessGroupIDOf pid pgid =
throwErrnoIfMinus1_ "setProcessGroupIDOf" (c_setpgid pid pgid)
foreign import ccall unsafe "setpgid"
c_setpgid :: CPid -> CPid -> IO CInt
{-# LINE 250 "System/Posix/Process/Common.hsc" #-}
{-# LINE 259 "System/Posix/Process/Common.hsc" #-}
createSession :: IO ProcessGroupID
createSession = throwErrnoIfMinus1 "createSession" c_setsid
foreign import ccall unsafe "setsid"
c_setsid :: IO CPid
{-# LINE 269 "System/Posix/Process/Common.hsc" #-}
data ProcessTimes
= ProcessTimes { elapsedTime :: ClockTick
, userTime :: ClockTick
, systemTime :: ClockTick
, childUserTime :: ClockTick
, childSystemTime :: ClockTick
}
{-# LINE 284 "System/Posix/Process/Common.hsc" #-}
getProcessTimes :: IO ProcessTimes
getProcessTimes = do
allocaBytes (32) $ \p_tms -> do
{-# LINE 290 "System/Posix/Process/Common.hsc" #-}
elapsed <- throwErrnoIfMinus1 "getProcessTimes" (c_times p_tms)
ut <- ((\hsc_ptr -> peekByteOff hsc_ptr 0)) p_tms
{-# LINE 292 "System/Posix/Process/Common.hsc" #-}
st <- ((\hsc_ptr -> peekByteOff hsc_ptr 8)) p_tms
{-# LINE 293 "System/Posix/Process/Common.hsc" #-}
cut <- ((\hsc_ptr -> peekByteOff hsc_ptr 16)) p_tms
{-# LINE 294 "System/Posix/Process/Common.hsc" #-}
cst <- ((\hsc_ptr -> peekByteOff hsc_ptr 24)) p_tms
{-# LINE 295 "System/Posix/Process/Common.hsc" #-}
return (ProcessTimes{ elapsedTime = elapsed,
userTime = ut,
systemTime = st,
childUserTime = cut,
childSystemTime = cst
})
data {-# CTYPE "struct tms" #-} CTms
foreign import capi unsafe "HsUnix.h times"
c_times :: Ptr CTms -> IO CClock
clocksPerSec :: ClockTick
{-# LINE 310 "System/Posix/Process/Common.hsc" #-}
clocksPerSec = c_clocks_per_sec
foreign import capi unsafe "HsUnix.h __hsunix_clocks_per_second"
c_clocks_per_sec :: CClock
{-# LINE 319 "System/Posix/Process/Common.hsc" #-}
{-# LINE 333 "System/Posix/Process/Common.hsc" #-}
{-# LINE 345 "System/Posix/Process/Common.hsc" #-}
nice :: Int -> IO ()
nice prio = do
resetErrno
res <- c_nice (fromIntegral prio)
when (res == -1) $ do
err <- getErrno
when (err /= eOK) (throwErrno "nice")
foreign import ccall unsafe "nice"
c_nice :: CInt -> IO CInt
{-# LINE 358 "System/Posix/Process/Common.hsc" #-}
getProcessPriority :: ProcessID -> IO Int
getProcessGroupPriority :: ProcessGroupID -> IO Int
getUserPriority :: UserID -> IO Int
{-# LINE 378 "System/Posix/Process/Common.hsc" #-}
getProcessPriority pid = do
r <- throwErrnoIfMinus1 "getProcessPriority" $
c_getpriority (0) (fromIntegral pid)
{-# LINE 382 "System/Posix/Process/Common.hsc" #-}
return (fromIntegral r)
getProcessGroupPriority pid = do
r <- throwErrnoIfMinus1 "getProcessPriority" $
c_getpriority (1) (fromIntegral pid)
{-# LINE 387 "System/Posix/Process/Common.hsc" #-}
return (fromIntegral r)
getUserPriority uid = do
r <- throwErrnoIfMinus1 "getUserPriority" $
c_getpriority (2) (fromIntegral uid)
{-# LINE 392 "System/Posix/Process/Common.hsc" #-}
return (fromIntegral r)
foreign import ccall unsafe "getpriority"
c_getpriority :: CInt -> CInt -> IO CInt
{-# LINE 398 "System/Posix/Process/Common.hsc" #-}
setProcessPriority :: ProcessID -> Int -> IO ()
setProcessGroupPriority :: ProcessGroupID -> Int -> IO ()
setUserPriority :: UserID -> Int -> IO ()
{-# LINE 418 "System/Posix/Process/Common.hsc" #-}
setProcessPriority pid val =
throwErrnoIfMinus1_ "setProcessPriority" $
c_setpriority (0) (fromIntegral pid) (fromIntegral val)
{-# LINE 422 "System/Posix/Process/Common.hsc" #-}
setProcessGroupPriority pid val =
throwErrnoIfMinus1_ "setProcessPriority" $
c_setpriority (1) (fromIntegral pid) (fromIntegral val)
{-# LINE 426 "System/Posix/Process/Common.hsc" #-}
setUserPriority uid val =
throwErrnoIfMinus1_ "setUserPriority" $
c_setpriority (2) (fromIntegral uid) (fromIntegral val)
{-# LINE 430 "System/Posix/Process/Common.hsc" #-}
foreign import ccall unsafe "setpriority"
c_setpriority :: CInt -> CInt -> CInt -> IO CInt
{-# LINE 435 "System/Posix/Process/Common.hsc" #-}
{-# LINE 471 "System/Posix/Process/Common.hsc" #-}
forkProcess :: IO () -> IO ProcessID
forkProcess action = do
mstate <- getMaskingState
let action' = case mstate of
Unmasked -> unsafeUnmask action
MaskedInterruptible -> action
MaskedUninterruptible -> uninterruptibleMask_ action
bracket
(newStablePtr (runIO action'))
freeStablePtr
(\stable -> throwErrnoIfMinus1 "forkProcess" (forkProcessPrim stable))
foreign import ccall "forkProcess" forkProcessPrim :: StablePtr (IO ()) -> IO CPid
forkProcessWithUnmask :: ((forall a . IO a -> IO a) -> IO ()) -> IO ProcessID
forkProcessWithUnmask action = forkProcess (action unsafeUnmask)
{-# LINE 497 "System/Posix/Process/Common.hsc" #-}
{-# LINE 506 "System/Posix/Process/Common.hsc" #-}
getProcessStatus :: Bool -> Bool -> ProcessID -> IO (Maybe ProcessStatus)
getProcessStatus block stopped pid =
alloca $ \wstatp -> do
pid' <- throwErrnoIfMinus1Retry "getProcessStatus"
(c_waitpid pid wstatp (waitOptions block stopped))
case pid' of
0 -> return Nothing
_ -> do ps <- readWaitStatus wstatp
return (Just ps)
foreign import ccall interruptible "waitpid"
c_waitpid :: CPid -> Ptr CInt -> CInt -> IO CPid
{-# LINE 531 "System/Posix/Process/Common.hsc" #-}
{-# LINE 543 "System/Posix/Process/Common.hsc" #-}
getGroupProcessStatus :: Bool
-> Bool
-> ProcessGroupID
-> IO (Maybe (ProcessID, ProcessStatus))
getGroupProcessStatus block stopped pgid =
alloca $ \wstatp -> do
pid <- throwErrnoIfMinus1Retry "getGroupProcessStatus"
(c_waitpid (-pgid) wstatp (waitOptions block stopped))
case pid of
0 -> return Nothing
_ -> do ps <- readWaitStatus wstatp
return (Just (pid, ps))
{-# LINE 568 "System/Posix/Process/Common.hsc" #-}
{-# LINE 577 "System/Posix/Process/Common.hsc" #-}
getAnyProcessStatus :: Bool -> Bool -> IO (Maybe (ProcessID, ProcessStatus))
getAnyProcessStatus block stopped = getGroupProcessStatus block stopped 1
{-# LINE 592 "System/Posix/Process/Common.hsc" #-}
{-# LINE 594 "System/Posix/Process/Common.hsc" #-}
waitOptions :: Bool -> Bool -> CInt
waitOptions False False = (1)
{-# LINE 598 "System/Posix/Process/Common.hsc" #-}
waitOptions False True = (3)
{-# LINE 599 "System/Posix/Process/Common.hsc" #-}
waitOptions True False = 0
waitOptions True True = (2)
{-# LINE 601 "System/Posix/Process/Common.hsc" #-}
readWaitStatus :: Ptr CInt -> IO ProcessStatus
readWaitStatus wstatp = do
wstat <- peek wstatp
decipherWaitStatus wstat
{-# LINE 610 "System/Posix/Process/Common.hsc" #-}
exitImmediately :: ExitCode -> IO a
exitImmediately status = do
_ <- c_exit (exitcode2Int status)
exitImmediately status
where
exitcode2Int ExitSuccess = 0
exitcode2Int (ExitFailure n) = fromIntegral n
foreign import ccall unsafe "exit"
c_exit :: CInt -> IO ()
{-# LINE 649 "System/Posix/Process/Common.hsc" #-}
{-# DEPRECATED createProcessGroup "This function is scheduled to be replaced by something different in the future, we therefore recommend that you do not use this version and use 'createProcessGroupFor' instead." #-}
createProcessGroup :: ProcessID -> IO ProcessGroupID
createProcessGroup pid = do
throwErrnoIfMinus1_ "createProcessGroup" (c_setpgid pid 0)
return pid
{-# DEPRECATED setProcessGroupID "This function is scheduled to be replaced by something different in the future, we therefore recommend that you do not use this version and use 'setProcessGroupIDOf' instead." #-}
setProcessGroupID :: ProcessID -> ProcessGroupID -> IO ()
setProcessGroupID pid pgid =
throwErrnoIfMinus1_ "setProcessGroupID" (c_setpgid pid pgid)
{-# LINE 677 "System/Posix/Process/Common.hsc" #-}