{-# LANGUAGE ForeignFunctionInterface #-} {-# CFILES System/Posix/waitpid.c #-} module System.Posix.Waitpid where import Control.Monad import Data.List import Foreign import Foreign.C import System.Posix.Signals (Signal) import System.Posix.Types (CPid) foreign import ccall unsafe "SystemPosixWaitpid_waitpid" c_waitpid :: CPid -> Ptr CInt -> CInt -> IO CPid data Flag = NoHang | IncludeUntraced | IncludeContinued deriving Show data Status = Exited Int | Signaled Signal | Stopped Signal | Continued deriving (Show, Eq) waitpid :: CPid -> [Flag] -> IO (Maybe (CPid, Status)) waitpid pid flags = alloca $ \status -> do child <- throwErrnoIfMinus1 "waitpid" $ c_waitpid pid status options stat <- peek status return $ guard (child /= 0) >> return (child, extractStatus stat) where options = foldl' (.|.) 0 (map flagValue flags) flagValue NoHang = 1 flagValue IncludeUntraced = 2 flagValue IncludeContinued = 4 extractStatus stat | stat < 0x10000 = Exited (fromIntegral stat) | stat < 0x20000 = Signaled (stat - 0x10000) | stat < 0x30000 = Stopped (stat - 0x20000) | stat == 0x30000 = Continued | otherwise = error $ "waitpid: unexpected status " ++ show stat