1 -----------------------------------------------------------------------------
3 -- Module : System.Posix.Signals
4 -- Copyright : (c) The University of Glasgow 2002
5 -- License : BSD-style (see the file libraries/base/LICENSE)
7 -- Maintainer : libraries@haskell.org
8 -- Stability : provisional
9 -- Portability : non-portable (requires POSIX)
11 -- POSIX signal support
13 -----------------------------------------------------------------------------
17 module System.Posix.Signals (
18 #ifndef mingw32_TARGET_OS
24 internalAbort, sigABRT,
25 realTimeAlarm, sigALRM,
27 processStatusChanged, sigCHLD,
28 continueProcess, sigCONT,
29 floatingPointException, sigFPE,
30 lostConnection, sigHUP,
31 illegalInstruction, sigILL,
32 keyboardSignal, sigINT,
34 openEndedPipe, sigPIPE,
35 keyboardTermination, sigQUIT,
36 segmentationViolation, sigSEGV,
37 softwareStop, sigSTOP,
38 softwareTermination, sigTERM,
39 keyboardStop, sigTSTP,
40 backgroundRead, sigTTIN,
41 backgroundWrite, sigTTOU,
42 userDefinedSignal1, sigUSR1,
43 userDefinedSignal2, sigUSR2,
45 pollableEvent, sigPOLL,
47 profilingTimerExpired, sigPROF,
48 badSystemCall, sigSYS,
49 breakpointTrap, sigTRAP,
50 urgentDataAvailable, sigURG,
51 virtualTimerExpired, sigVTALRM,
52 cpuTimeLimitExceeded, sigXCPU,
53 fileSizeLimitExceeded, sigXFSZ,
60 #ifdef __GLASGOW_HASKELL__
68 emptySignalSet, fullSignalSet,
69 addSignal, deleteSignal, inSignalSet,
71 -- * The process signal mask
72 getSignalMask, setSignalMask, blockSignals, unblockSignals,
77 -- * Waiting for signals
78 getPendingSignals, awaitSignal,
80 #ifdef __GLASGOW_HASKELL__
81 -- * The @NOCLDSTOP@ flag
82 setStoppedChildFlag, queryStoppedChildFlag,
85 -- MISSING FUNCTIONALITY:
86 -- sigaction(), (inc. the sigaction structure + flags etc.)
87 -- the siginfo structure
89 -- sighold, sigignore, sigpause, sigrelse, sigset
94 #ifdef __GLASGOW_HASKELL__
102 import System.IO.Unsafe
103 import System.Posix.Types
104 import System.Posix.Internals
106 #ifndef mingw32_TARGET_OS
109 -- -----------------------------------------------------------------------------
118 sigABRT = (#const SIGABRT) :: CInt
119 sigALRM = (#const SIGALRM) :: CInt
120 sigBUS = (#const SIGBUS) :: CInt
121 sigCHLD = (#const SIGCHLD) :: CInt
122 sigCONT = (#const SIGCONT) :: CInt
123 sigFPE = (#const SIGFPE) :: CInt
124 sigHUP = (#const SIGHUP) :: CInt
125 sigILL = (#const SIGILL) :: CInt
126 sigINT = (#const SIGINT) :: CInt
127 sigKILL = (#const SIGKILL) :: CInt
128 sigPIPE = (#const SIGPIPE) :: CInt
129 sigQUIT = (#const SIGQUIT) :: CInt
130 sigSEGV = (#const SIGSEGV) :: CInt
131 sigSTOP = (#const SIGSTOP) :: CInt
132 sigTERM = (#const SIGTERM) :: CInt
133 sigTSTP = (#const SIGTSTP) :: CInt
134 sigTTIN = (#const SIGTTIN) :: CInt
135 sigTTOU = (#const SIGTTOU) :: CInt
136 sigUSR1 = (#const SIGUSR1) :: CInt
137 sigUSR2 = (#const SIGUSR2) :: CInt
139 sigPOLL = (#const SIGPOLL) :: CInt
141 sigPROF = (#const SIGPROF) :: CInt
142 sigSYS = (#const SIGSYS) :: CInt
143 sigTRAP = (#const SIGTRAP) :: CInt
144 sigURG = (#const SIGURG) :: CInt
145 sigVTALRM = (#const SIGVTALRM) :: CInt
146 sigXCPU = (#const SIGXCPU) :: CInt
147 sigXFSZ = (#const SIGXFSZ) :: CInt
149 foreign import ccall unsafe "__hsposix_SIGABRT" sigABRT :: CInt
150 foreign import ccall unsafe "__hsposix_SIGALRM" sigALRM :: CInt
151 foreign import ccall unsafe "__hsposix_SIGBUS" sigBUS :: CInt
152 foreign import ccall unsafe "__hsposix_SIGCHLD" sigCHLD :: CInt
153 foreign import ccall unsafe "__hsposix_SIGCONT" sigCONT :: CInt
154 foreign import ccall unsafe "__hsposix_SIGFPE" sigFPE :: CInt
155 foreign import ccall unsafe "__hsposix_SIGHUP" sigHUP :: CInt
156 foreign import ccall unsafe "__hsposix_SIGILL" sigILL :: CInt
157 foreign import ccall unsafe "__hsposix_SIGINT" sigINT :: CInt
158 foreign import ccall unsafe "__hsposix_SIGKILL" sigKILL :: CInt
159 foreign import ccall unsafe "__hsposix_SIGPIPE" sigPIPE :: CInt
160 foreign import ccall unsafe "__hsposix_SIGQUIT" sigQUIT :: CInt
161 foreign import ccall unsafe "__hsposix_SIGSEGV" sigSEGV :: CInt
162 foreign import ccall unsafe "__hsposix_SIGSTOP" sigSTOP :: CInt
163 foreign import ccall unsafe "__hsposix_SIGTERM" sigTERM :: CInt
164 foreign import ccall unsafe "__hsposix_SIGTSTP" sigTSTP :: CInt
165 foreign import ccall unsafe "__hsposix_SIGTTIN" sigTTIN :: CInt
166 foreign import ccall unsafe "__hsposix_SIGTTOU" sigTTOU :: CInt
167 foreign import ccall unsafe "__hsposix_SIGUSR1" sigUSR1 :: CInt
168 foreign import ccall unsafe "__hsposix_SIGUSR2" sigUSR2 :: CInt
170 foreign import ccall unsafe "__hsposix_SIGPOLL" sigPOLL :: CInt
172 foreign import ccall unsafe "__hsposix_SIGPROF" sigPROF :: CInt
173 foreign import ccall unsafe "__hsposix_SIGSYS" sigSYS :: CInt
174 foreign import ccall unsafe "__hsposix_SIGTRAP" sigTRAP :: CInt
175 foreign import ccall unsafe "__hsposix_SIGURG" sigURG :: CInt
176 foreign import ccall unsafe "__hsposix_SIGVTALRM" sigVTALRM :: CInt
177 foreign import ccall unsafe "__hsposix_SIGXCPU" sigXCPU :: CInt
178 foreign import ccall unsafe "__hsposix_SIGXFSZ" sigXFSZ :: CInt
179 #endif /* __HUGS__ */
181 internalAbort ::Signal
182 internalAbort = sigABRT
184 realTimeAlarm :: Signal
185 realTimeAlarm = sigALRM
190 processStatusChanged :: Signal
191 processStatusChanged = sigCHLD
193 #ifndef cygwin32_TARGET_OS
194 continueProcess :: Signal
195 continueProcess = sigCONT
198 floatingPointException :: Signal
199 floatingPointException = sigFPE
201 lostConnection :: Signal
202 lostConnection = sigHUP
204 illegalInstruction :: Signal
205 illegalInstruction = sigILL
207 keyboardSignal :: Signal
208 keyboardSignal = sigINT
210 killProcess :: Signal
211 killProcess = sigKILL
213 openEndedPipe :: Signal
214 openEndedPipe = sigPIPE
216 keyboardTermination :: Signal
217 keyboardTermination = sigQUIT
219 segmentationViolation :: Signal
220 segmentationViolation = sigSEGV
222 softwareStop :: Signal
223 softwareStop = sigSTOP
225 softwareTermination :: Signal
226 softwareTermination = sigTERM
228 keyboardStop :: Signal
229 keyboardStop = sigTSTP
231 backgroundRead :: Signal
232 backgroundRead = sigTTIN
234 backgroundWrite :: Signal
235 backgroundWrite = sigTTOU
237 userDefinedSignal1 :: Signal
238 userDefinedSignal1 = sigUSR1
240 userDefinedSignal2 :: Signal
241 userDefinedSignal2 = sigUSR2
244 pollableEvent :: Signal
245 pollableEvent = sigPOLL
248 profilingTimerExpired :: Signal
249 profilingTimerExpired = sigPROF
251 badSystemCall :: Signal
252 badSystemCall = sigSYS
254 breakpointTrap :: Signal
255 breakpointTrap = sigTRAP
257 urgentDataAvailable :: Signal
258 urgentDataAvailable = sigURG
260 virtualTimerExpired :: Signal
261 virtualTimerExpired = sigVTALRM
263 cpuTimeLimitExceeded :: Signal
264 cpuTimeLimitExceeded = sigXCPU
266 fileSizeLimitExceeded :: Signal
267 fileSizeLimitExceeded = sigXFSZ
269 -- -----------------------------------------------------------------------------
270 -- Signal-related functions
272 signalProcess :: Signal -> ProcessID -> IO ()
273 signalProcess sig pid
274 = throwErrnoIfMinus1_ "signalProcess" (c_kill (fromIntegral pid) sig)
276 foreign import ccall unsafe "kill"
277 c_kill :: CPid -> CInt -> IO CInt
279 signalProcessGroup :: Signal -> ProcessGroupID -> IO ()
280 signalProcessGroup sig pgid
281 = throwErrnoIfMinus1_ "signalProcessGroup" (c_killpg (fromIntegral pgid) sig)
283 foreign import ccall unsafe "killpg"
284 c_killpg :: CPid -> CInt -> IO CInt
286 raiseSignal :: Signal -> IO ()
287 raiseSignal sig = throwErrnoIfMinus1_ "raiseSignal" (c_raise sig)
289 foreign import ccall unsafe "raise"
290 c_raise :: CInt -> IO CInt
292 #ifdef __GLASGOW_HASKELL__
293 data Handler = Default
299 installHandler :: Signal
301 -> Maybe SignalSet -- other signals to block
302 -> IO Handler -- old handler
304 #ifdef __PARALLEL_HASKELL__
306 error "installHandler: not available for Parallel Haskell"
309 installHandler int handler maybe_mask = do
311 Nothing -> install' nullPtr
312 Just (SignalSet x) -> withForeignPtr x $ install'
317 rc <- case handler of
318 Default -> stg_sig_install int (#const STG_SIG_DFL) p_sp mask
319 Ignore -> stg_sig_install int (#const STG_SIG_IGN) p_sp mask
320 Catch m -> install'' m p_sp mask int (#const STG_SIG_HAN)
321 CatchOnce m -> install'' m p_sp mask int (#const STG_SIG_RST)
324 (#const STG_SIG_DFL) -> return Default
325 (#const STG_SIG_IGN) -> return Ignore
326 (#const STG_SIG_ERR) -> throwErrno "installHandler"
327 (#const STG_SIG_HAN) -> do
328 m <- peekHandler p_sp
330 (#const STG_SIG_RST) -> do
331 m <- peekHandler p_sp
334 install'' m p_sp mask int reset = do
335 sptr <- newStablePtr m
337 stg_sig_install int reset p_sp mask
339 peekHandler p_sp = do
343 foreign import ccall unsafe
344 stg_sig_install :: CInt -> CInt -> Ptr (StablePtr (IO ())) -> Ptr CSigset
347 #endif /* !__PARALLEL_HASKELL__ */
348 #endif /* __GLASGOW_HASKELL__ */
350 -- -----------------------------------------------------------------------------
353 scheduleAlarm :: Int -> IO Int
354 scheduleAlarm secs = do
355 r <- c_alarm (fromIntegral secs)
356 return (fromIntegral r)
358 foreign import ccall unsafe "alarm"
359 c_alarm :: CUInt -> IO CUInt
361 #ifdef __GLASGOW_HASKELL__
362 -- -----------------------------------------------------------------------------
363 -- The NOCLDSTOP flag
365 foreign import ccall "&nocldstop" nocldstop :: Ptr Int
367 -- | Tells the system whether or not to set the @SA_NOCLDSTOP@ flag when
368 -- installing new signal handlers.
369 setStoppedChildFlag :: Bool -> IO Bool
370 setStoppedChildFlag b = do
373 return (rc == (0::Int))
375 x = case b of {True -> 0; False -> 1}
377 -- | Queries the current state of the stopped child flag.
378 queryStoppedChildFlag :: IO Bool
379 queryStoppedChildFlag = do
381 return (rc == (0::Int))
382 #endif /* __GLASGOW_HASKELL__ */
384 -- -----------------------------------------------------------------------------
385 -- Manipulating signal sets
387 newtype SignalSet = SignalSet (ForeignPtr CSigset)
389 emptySignalSet :: SignalSet
390 emptySignalSet = unsafePerformIO $ do
391 fp <- mallocForeignPtrBytes sizeof_sigset_t
392 throwErrnoIfMinus1_ "emptySignalSet" (withForeignPtr fp $ c_sigemptyset)
393 return (SignalSet fp)
395 fullSignalSet :: SignalSet
396 fullSignalSet = unsafePerformIO $ do
397 fp <- mallocForeignPtrBytes sizeof_sigset_t
398 throwErrnoIfMinus1_ "fullSignalSet" (withForeignPtr fp $ c_sigfillset)
399 return (SignalSet fp)
401 infixr `addSignal`, `deleteSignal`
402 addSignal :: Signal -> SignalSet -> SignalSet
403 addSignal sig (SignalSet fp1) = unsafePerformIO $ do
404 fp2 <- mallocForeignPtrBytes sizeof_sigset_t
405 withForeignPtr fp1 $ \p1 ->
406 withForeignPtr fp2 $ \p2 -> do
407 copyBytes p2 p1 sizeof_sigset_t
408 throwErrnoIfMinus1_ "addSignal" (c_sigaddset p2 sig)
409 return (SignalSet fp2)
411 deleteSignal :: Signal -> SignalSet -> SignalSet
412 deleteSignal sig (SignalSet fp1) = unsafePerformIO $ do
413 fp2 <- mallocForeignPtrBytes sizeof_sigset_t
414 withForeignPtr fp1 $ \p1 ->
415 withForeignPtr fp2 $ \p2 -> do
416 copyBytes p2 p1 sizeof_sigset_t
417 throwErrnoIfMinus1_ "deleteSignal" (c_sigdelset p2 sig)
418 return (SignalSet fp2)
420 inSignalSet :: Signal -> SignalSet -> Bool
421 inSignalSet sig (SignalSet fp) = unsafePerformIO $
422 withForeignPtr fp $ \p -> do
423 r <- throwErrnoIfMinus1 "inSignalSet" (c_sigismember p sig)
426 getSignalMask :: IO SignalSet
428 fp <- mallocForeignPtrBytes sizeof_sigset_t
429 withForeignPtr fp $ \p ->
430 throwErrnoIfMinus1_ "getSignalMask" (c_sigprocmask 0 nullPtr p)
431 return (SignalSet fp)
433 sigProcMask :: String -> CInt -> SignalSet -> IO ()
434 sigProcMask fn how (SignalSet set) =
435 withForeignPtr set $ \p_set ->
436 throwErrnoIfMinus1_ fn (c_sigprocmask how p_set nullPtr)
438 setSignalMask :: SignalSet -> IO ()
439 setSignalMask set = sigProcMask "setSignalMask" c_SIG_SETMASK set
441 blockSignals :: SignalSet -> IO ()
442 blockSignals set = sigProcMask "blockSignals" c_SIG_BLOCK set
444 unblockSignals :: SignalSet -> IO ()
445 unblockSignals set = sigProcMask "unblockSignals" c_SIG_UNBLOCK set
447 getPendingSignals :: IO SignalSet
448 getPendingSignals = do
449 fp <- mallocForeignPtrBytes sizeof_sigset_t
450 withForeignPtr fp $ \p ->
451 throwErrnoIfMinus1_ "getPendingSignals" (c_sigpending p)
452 return (SignalSet fp)
454 #ifndef cygwin32_TARGET_OS
455 awaitSignal :: Maybe SignalSet -> IO ()
456 awaitSignal maybe_sigset = do
457 fp <- case maybe_sigset of
458 Nothing -> do SignalSet fp <- getSignalMask; return fp
459 Just (SignalSet fp) -> return fp
460 withForeignPtr fp $ \p -> do
463 -- ignore the return value; according to the docs it can only ever be
464 -- (-1) with errno set to EINTR.
466 foreign import ccall unsafe "sigsuspend"
467 c_sigsuspend :: Ptr CSigset -> IO CInt
471 foreign import ccall unsafe "sigdelset"
472 c_sigdelset :: Ptr CSigset -> CInt -> IO CInt
474 foreign import ccall unsafe "sigfillset"
475 c_sigfillset :: Ptr CSigset -> IO CInt
477 foreign import ccall unsafe "sigismember"
478 c_sigismember :: Ptr CSigset -> CInt -> IO CInt
480 foreign import ccall unsafe "__hscore_sigdelset"
481 c_sigdelset :: Ptr CSigset -> CInt -> IO CInt
483 foreign import ccall unsafe "__hscore_sigfillset"
484 c_sigfillset :: Ptr CSigset -> IO CInt
486 foreign import ccall unsafe "__hscore_sigismember"
487 c_sigismember :: Ptr CSigset -> CInt -> IO CInt
488 #endif /* __HUGS__ */
490 foreign import ccall unsafe "sigpending"
491 c_sigpending :: Ptr CSigset -> IO CInt
494 c_SIG_BLOCK = (#const SIG_BLOCK) :: CInt
495 c_SIG_SETMASK = (#const SIG_SETMASK) :: CInt
496 c_SIG_UNBLOCK = (#const SIG_UNBLOCK) :: CInt
498 foreign import ccall unsafe "__hsposix_SIG_BLOCK" c_SIG_BLOCK :: CInt
499 foreign import ccall unsafe "__hsposix_SIG_SETMASK" c_SIG_SETMASK :: CInt
500 foreign import ccall unsafe "__hsposix_SIG_UNBLOCK" c_SIG_UNBLOCK :: CInt
501 #endif /* __HUGS__ */
503 #endif /* mingw32_TARGET_OS */