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,
44 pollableEvent, sigPOLL,
45 profilingTimerExpired, sigPROF,
46 badSystemCall, sigSYS,
47 breakpointTrap, sigTRAP,
48 urgentDataAvailable, sigURG,
49 virtualTimerExpired, sigVTALRM,
50 cpuTimeLimitExceeded, sigXCPU,
51 fileSizeLimitExceeded, sigXFSZ,
64 emptySignalSet, fullSignalSet,
65 addSignal, deleteSignal, inSignalSet,
67 -- * The process signal mask
68 getSignalMask, setSignalMask, blockSignals, unblockSignals,
73 -- * Waiting for signals
74 getPendingSignals, awaitSignal,
76 -- MISSING FUNCTIONALITY:
77 -- sigaction(), (inc. the sigaction structure + flags etc.)
78 -- the siginfo structure
80 -- sighold, sigignore, sigpause, sigrelse, sigset
89 import System.IO.Unsafe
90 import System.Posix.Types
93 #ifndef mingw32_TARGET_OS
96 -- -----------------------------------------------------------------------------
104 foreign import ccall "__hsposix_SIGABRT" sigABRT :: CInt
105 foreign import ccall "__hsposix_SIGALRM" sigALRM :: CInt
106 foreign import ccall "__hsposix_SIGBUS" sigBUS :: CInt
107 foreign import ccall "__hsposix_SIGCHLD" sigCHLD :: CInt
108 foreign import ccall "__hsposix_SIGCONT" sigCONT :: CInt
109 foreign import ccall "__hsposix_SIGFPE" sigFPE :: CInt
110 foreign import ccall "__hsposix_SIGHUP" sigHUP :: CInt
111 foreign import ccall "__hsposix_SIGILL" sigILL :: CInt
112 foreign import ccall "__hsposix_SIGINT" sigINT :: CInt
113 foreign import ccall "__hsposix_SIGKILL" sigKILL :: CInt
114 foreign import ccall "__hsposix_SIGPIPE" sigPIPE :: CInt
115 foreign import ccall "__hsposix_SIGQUIT" sigQUIT :: CInt
116 foreign import ccall "__hsposix_SIGSEGV" sigSEGV :: CInt
117 foreign import ccall "__hsposix_SIGSTOP" sigSTOP :: CInt
118 foreign import ccall "__hsposix_SIGTERM" sigTERM :: CInt
119 foreign import ccall "__hsposix_SIGTSTP" sigTSTP :: CInt
120 foreign import ccall "__hsposix_SIGTTIN" sigTTIN :: CInt
121 foreign import ccall "__hsposix_SIGTTOU" sigTTOU :: CInt
122 foreign import ccall "__hsposix_SIGUSR1" sigUSR1 :: CInt
123 foreign import ccall "__hsposix_SIGUSR2" sigUSR2 :: CInt
124 foreign import ccall "__hsposix_SIGPOLL" sigPOLL :: CInt
125 foreign import ccall "__hsposix_SIGPROF" sigPROF :: CInt
126 foreign import ccall "__hsposix_SIGSYS" sigSYS :: CInt
127 foreign import ccall "__hsposix_SIGTRAP" sigTRAP :: CInt
128 foreign import ccall "__hsposix_SIGURG" sigURG :: CInt
129 foreign import ccall "__hsposix_SIGVTALRM" sigVTALRM :: CInt
130 foreign import ccall "__hsposix_SIGXCPU" sigXCPU :: CInt
131 foreign import ccall "__hsposix_SIGXFSZ" sigXFSZ :: CInt
133 internalAbort ::Signal
134 internalAbort = sigABRT
136 realTimeAlarm :: Signal
137 realTimeAlarm = sigALRM
142 processStatusChanged :: Signal
143 processStatusChanged = sigCHLD
145 #ifndef cygwin32_TARGET_OS
146 continueProcess :: Signal
147 continueProcess = sigCONT
150 floatingPointException :: Signal
151 floatingPointException = sigFPE
153 lostConnection :: Signal
154 lostConnection = sigHUP
156 illegalInstruction :: Signal
157 illegalInstruction = sigILL
159 keyboardSignal :: Signal
160 keyboardSignal = sigINT
162 killProcess :: Signal
163 killProcess = sigKILL
165 openEndedPipe :: Signal
166 openEndedPipe = sigPIPE
168 keyboardTermination :: Signal
169 keyboardTermination = sigQUIT
171 segmentationViolation :: Signal
172 segmentationViolation = sigSEGV
174 softwareStop :: Signal
175 softwareStop = sigSTOP
177 softwareTermination :: Signal
178 softwareTermination = sigTERM
180 keyboardStop :: Signal
181 keyboardStop = sigTSTP
183 backgroundRead :: Signal
184 backgroundRead = sigTTIN
186 backgroundWrite :: Signal
187 backgroundWrite = sigTTOU
189 userDefinedSignal1 :: Signal
190 userDefinedSignal1 = sigUSR1
192 userDefinedSignal2 :: Signal
193 userDefinedSignal2 = sigUSR2
195 pollableEvent :: Signal
196 pollableEvent = sigPOLL
198 profilingTimerExpired :: Signal
199 profilingTimerExpired = sigPROF
201 badSystemCall :: Signal
202 badSystemCall = sigSYS
204 breakpointTrap :: Signal
205 breakpointTrap = sigTRAP
207 urgentDataAvailable :: Signal
208 urgentDataAvailable = sigURG
210 virtualTimerExpired :: Signal
211 virtualTimerExpired = sigVTALRM
213 cpuTimeLimitExceeded :: Signal
214 cpuTimeLimitExceeded = sigXCPU
216 fileSizeLimitExceeded :: Signal
217 fileSizeLimitExceeded = sigXFSZ
219 -- -----------------------------------------------------------------------------
220 -- Signal-related functions
222 signalProcess :: Signal -> ProcessID -> IO ()
223 signalProcess sig pid
224 = throwErrnoIfMinus1_ "signalProcess" (c_kill (fromIntegral pid) sig)
226 foreign import ccall unsafe "kill"
227 c_kill :: CPid -> CInt -> IO CInt
229 signalProcessGroup :: Signal -> ProcessGroupID -> IO ()
230 signalProcessGroup sig pgid
231 = throwErrnoIfMinus1_ "signalProcessGroup" (c_killpg (fromIntegral pgid) sig)
233 foreign import ccall unsafe "killpg"
234 c_killpg :: CPid -> CInt -> IO CInt
236 raiseSignal :: Signal -> IO ()
237 raiseSignal sig = throwErrnoIfMinus1_ "raiseSignal" (c_raise sig)
239 foreign import ccall unsafe "raise"
240 c_raise :: CInt -> IO CInt
242 data Handler = Default
247 installHandler :: Signal
249 -> Maybe SignalSet -- other signals to block
250 -> IO Handler -- old handler
252 #ifdef __PARALLEL_HASKELL__
254 error "installHandler: not available for Parallel Haskell"
257 installHandler int handler maybe_mask = do
259 Nothing -> install' nullPtr
260 Just (SignalSet x) -> withForeignPtr x $ install'
265 rc <- case handler of
266 Default -> stg_sig_install int (#const STG_SIG_DFL) p_sp mask
267 Ignore -> stg_sig_install int (#const STG_SIG_IGN) p_sp mask
268 Catch m -> do sptr <- newStablePtr m
270 stg_sig_install int (#const STG_SIG_HAN) p_sp mask
273 (#const STG_SIG_DFL) -> return Default
274 (#const STG_SIG_IGN) -> return Ignore
275 (#const STG_SIG_ERR) -> throwErrno "installHandler"
276 (#const STG_SIG_HAN) -> do
278 m <- deRefStablePtr osptr
281 foreign import ccall unsafe
282 stg_sig_install :: CInt -> CInt -> Ptr (StablePtr (IO ())) -> Ptr CSigset
285 #endif // !__PARALLEL_HASKELL__
287 -- -----------------------------------------------------------------------------
290 scheduleAlarm :: Int -> IO Int
291 scheduleAlarm secs = do
292 r <- c_alarm (fromIntegral secs)
293 return (fromIntegral r)
295 foreign import ccall unsafe "alarm"
296 c_alarm :: CUInt -> IO CUInt
298 -- -----------------------------------------------------------------------------
299 -- Manipulating signal sets
301 newtype SignalSet = SignalSet (ForeignPtr CSigset)
303 emptySignalSet :: SignalSet
304 emptySignalSet = unsafePerformIO $ do
305 fp <- mallocForeignPtrBytes sizeof_sigset_t
306 throwErrnoIfMinus1_ "emptySignalSet" (withForeignPtr fp $ c_sigemptyset)
307 return (SignalSet fp)
309 fullSignalSet :: SignalSet
310 fullSignalSet = unsafePerformIO $ do
311 fp <- mallocForeignPtrBytes sizeof_sigset_t
312 throwErrnoIfMinus1_ "fullSignalSet" (withForeignPtr fp $ c_sigfillset)
313 return (SignalSet fp)
315 infixr `addSignal`, `deleteSignal`
316 addSignal :: Signal -> SignalSet -> SignalSet
317 addSignal sig (SignalSet fp1) = unsafePerformIO $ do
318 fp2 <- mallocForeignPtrBytes sizeof_sigset_t
319 withForeignPtr fp1 $ \p1 ->
320 withForeignPtr fp2 $ \p2 -> do
321 copyBytes p2 p1 sizeof_sigset_t
322 throwErrnoIfMinus1_ "addSignal" (c_sigaddset p2 sig)
323 return (SignalSet fp2)
325 deleteSignal :: Signal -> SignalSet -> SignalSet
326 deleteSignal sig (SignalSet fp1) = unsafePerformIO $ do
327 fp2 <- mallocForeignPtrBytes sizeof_sigset_t
328 withForeignPtr fp1 $ \p1 ->
329 withForeignPtr fp2 $ \p2 -> do
330 copyBytes p2 p1 sizeof_sigset_t
331 throwErrnoIfMinus1_ "deleteSignal" (c_sigdelset p2 sig)
332 return (SignalSet fp2)
334 inSignalSet :: Signal -> SignalSet -> Bool
335 inSignalSet sig (SignalSet fp) = unsafePerformIO $
336 withForeignPtr fp $ \p -> do
337 r <- throwErrnoIfMinus1 "inSignalSet" (c_sigismember p sig)
340 getSignalMask :: IO SignalSet
342 fp <- mallocForeignPtrBytes sizeof_sigset_t
343 withForeignPtr fp $ \p ->
344 throwErrnoIfMinus1_ "getSignalMask" (c_sigprocmask 0 p nullPtr)
345 return (SignalSet fp)
347 sigProcMask :: String -> CInt -> SignalSet -> IO ()
348 sigProcMask fn how (SignalSet set) =
349 withForeignPtr set $ \p_set ->
350 throwErrnoIfMinus1_ fn (c_sigprocmask how p_set nullPtr)
352 setSignalMask :: SignalSet -> IO ()
353 setSignalMask set = sigProcMask "setSignalMask" c_SIG_SETMASK set
355 blockSignals :: SignalSet -> IO ()
356 blockSignals set = sigProcMask "blockSignals" c_SIG_BLOCK set
358 unblockSignals :: SignalSet -> IO ()
359 unblockSignals set = sigProcMask "unblockSignals" c_SIG_UNBLOCK set
361 getPendingSignals :: IO SignalSet
362 getPendingSignals = do
363 fp <- mallocForeignPtrBytes sizeof_sigset_t
364 withForeignPtr fp $ \p ->
365 throwErrnoIfMinus1_ "getPendingSignals" (c_sigpending p)
366 return (SignalSet fp)
368 #ifndef cygwin32_TARGET_OS
369 awaitSignal :: Maybe SignalSet -> IO ()
370 awaitSignal maybe_sigset = do
371 fp <- case maybe_sigset of
372 Nothing -> do SignalSet fp <- getSignalMask; return fp
373 Just (SignalSet fp) -> return fp
374 withForeignPtr fp $ \p -> do
377 -- ignore the return value; according to the docs it can only ever be
378 -- (-1) with errno set to EINTR.
380 foreign import ccall unsafe "sigsuspend"
381 c_sigsuspend :: Ptr CSigset -> IO CInt
384 foreign import ccall unsafe "__hscore_sigdelset"
385 c_sigdelset :: Ptr CSigset -> CInt -> IO CInt
387 foreign import ccall unsafe "__hscore_sigfillset"
388 c_sigfillset :: Ptr CSigset -> IO CInt
390 foreign import ccall unsafe "__hscore_sigismember"
391 c_sigismember :: Ptr CSigset -> CInt -> IO CInt
393 foreign import ccall unsafe "sigpending"
394 c_sigpending :: Ptr CSigset -> IO CInt
396 foreign import ccall unsafe "__hsposix_SIG_BLOCK" c_SIG_BLOCK :: CInt
397 foreign import ccall unsafe "__hsposix_SIG_SETMASK" c_SIG_SETMASK :: CInt
398 foreign import ccall unsafe "__hsposix_SIG_UNBLOCK" c_SIG_UNBLOCK :: CInt
400 #endif /* mingw32_TARGET_OS */