1 /* -----------------------------------------------------------------------------
2 * $Id: Signals.c,v 1.23 2002/03/12 13:57:14 simonmar Exp $
4 * (c) The GHC Team, 1998-1999
6 * Signal processing / handling.
8 * ---------------------------------------------------------------------------*/
10 /* This is non-Posix-compliant.
11 #include "PosixSource.h"
19 #include "StablePriv.h"
21 #ifdef alpha_TARGET_ARCH
22 #include <machine/fpu.h>
25 #ifndef mingw32_TARGET_OS
29 /* SUP: The type of handlers is a little bit, well, doubtful... */
30 static StgInt *handlers = NULL; /* Dynamically grown array of signal handlers */
31 static StgInt nHandlers = 0; /* Size of handlers array */
33 static nat n_haskell_handlers = 0;
35 #define N_PENDING_HANDLERS 16
37 StgPtr pending_handler_buf[N_PENDING_HANDLERS];
38 StgPtr *next_pending_handler = pending_handler_buf;
42 /* -----------------------------------------------------------------------------
43 * Allocate/resize the table of signal handlers.
44 * -------------------------------------------------------------------------- */
55 handlers = (StgInt *) malloc((sig + 1) * sizeof(StgInt));
57 handlers = (StgInt *) realloc(handlers, (sig + 1) * sizeof(StgInt));
59 if (handlers == NULL) {
60 // don't fflush(stdout); WORKAROUND bug in Linux glibc
61 barf("VM exhausted (in more_handlers)");
63 for(i = nHandlers; i <= sig; i++)
64 // Fill in the new slots with default actions
65 handlers[i] = STG_SIG_DFL;
70 /* -----------------------------------------------------------------------------
73 * It seems that shells tend to put stdin back into blocking mode
74 * following a suspend/resume of the process. Here we arrange to put
75 * it back into non-blocking mode. We don't do anything to
76 * stdout/stderr because these handles don't get put into non-blocking
77 * mode at all - see the comments on stdout/stderr in PrelHandle.hsc.
78 * -------------------------------------------------------------------------- */
81 cont_handler(int sig STG_UNUSED)
86 /* -----------------------------------------------------------------------------
87 * Low-level signal handler
89 * Places the requested handler on a stack of pending handlers to be
90 * started up at the next context switch.
91 * -------------------------------------------------------------------------- */
94 generic_handler(int sig)
98 /* Can't call allocate from here. Probably can't call malloc
99 either. However, we have to schedule a new thread somehow.
101 It's probably ok to request a context switch and allow the
102 scheduler to start the handler thread, but how do we
103 communicate this to the scheduler?
105 We need some kind of locking, but with low overhead (i.e. no
106 blocking signals every time around the scheduler).
108 Signal Handlers are atomic (i.e. they can't be interrupted), and
109 we can make use of this. We just need to make sure the
110 critical section of the scheduler can't be interrupted - the
111 only way to do this is to block signals. However, we can lower
112 the overhead by only blocking signals when there are any
113 handlers to run, i.e. the set of pending handlers is
117 /* We use a stack to store the pending signals. We can't
118 dynamically grow this since we can't allocate any memory from
119 within a signal handler.
121 Hence unfortunately we have to bomb out if the buffer
122 overflows. It might be acceptable to carry on in certain
123 circumstances, depending on the signal.
126 *next_pending_handler++ = deRefStablePtr((StgStablePtr)handlers[sig]);
129 if (next_pending_handler == &pending_handler_buf[N_PENDING_HANDLERS]) {
130 barf("too many pending signals");
133 // re-establish the signal handler, and carry on
134 sigemptyset(&signals);
135 sigaddset(&signals, sig);
136 sigprocmask(SIG_UNBLOCK, &signals, NULL);
138 // *always* do the SIGCONT handler, even if the user overrides it.
139 if (sig == SIGCONT) {
146 /* -----------------------------------------------------------------------------
147 * Blocking/Unblocking of the user signals
148 * -------------------------------------------------------------------------- */
150 static sigset_t userSignals;
151 static sigset_t savedSignals;
154 initUserSignals(void)
156 sigemptyset(&userSignals);
160 blockUserSignals(void)
162 sigprocmask(SIG_SETMASK, &userSignals, &savedSignals);
166 unblockUserSignals(void)
168 sigprocmask(SIG_SETMASK, &savedSignals, NULL);
172 anyUserHandlers(void)
174 return n_haskell_handlers != 0;
178 awaitUserSignals(void)
180 while (!signals_pending() && !interrupted) {
185 /* -----------------------------------------------------------------------------
186 * Install a Haskell signal handler.
187 * -------------------------------------------------------------------------- */
190 stg_sig_install(StgInt sig, StgInt spi, StgStablePtr handler, sigset_t *mask)
193 struct sigaction action;
196 // Block the signal until we figure out what to do
197 // Count on this to fail if the signal number is invalid
198 if (sig < 0 || sigemptyset(&signals) ||
199 sigaddset(&signals, sig) || sigprocmask(SIG_BLOCK, &signals, NULL)) {
205 previous_spi = handlers[sig];
209 handlers[sig] = STG_SIG_IGN;
210 sigdelset(&userSignals, sig);
211 action.sa_handler = SIG_IGN;
215 handlers[sig] = STG_SIG_DFL;
216 sigdelset(&userSignals, sig);
217 action.sa_handler = SIG_DFL;
221 handlers[sig] = (StgInt)handler;
222 sigaddset(&userSignals, sig);
223 action.sa_handler = generic_handler;
224 n_haskell_handlers++;
228 barf("stg_sig_install: bad spi");
232 action.sa_mask = *mask;
234 sigemptyset(&action.sa_mask);
236 action.sa_flags = sig == SIGCHLD && nocldstop ? SA_NOCLDSTOP : 0;
238 if (sigaction(sig, &action, NULL) ||
239 sigprocmask(SIG_UNBLOCK, &signals, NULL))
241 // need to return an error code, so avoid a stable pointer leak
242 // by freeing the previous handler if there was one.
243 if (previous_spi >= 0) {
244 freeStablePtr(stgCast(StgStablePtr,handlers[sig]));
245 n_haskell_handlers--;
253 /* -----------------------------------------------------------------------------
254 * Creating new threads for the pending signal handlers.
255 * -------------------------------------------------------------------------- */
257 startSignalHandlers(void)
261 while (next_pending_handler != pending_handler_buf) {
263 next_pending_handler--;
266 createIOThread(RtsFlags.GcFlags.initialStkSize,
267 (StgClosure *) *next_pending_handler));
270 unblockUserSignals();
275 stg_sig_install(StgInt sig, StgInt spi, StgStablePtr handler, sigset_t *mask)
277 // don't fflush(stdout); WORKAROUND bug in Linux glibc
278 barf("no signal handling support in a parallel implementation");
282 startSignalHandlers(void)
287 /* -----------------------------------------------------------------------------
290 * We like to shutdown nicely after receiving a SIGINT, write out the
291 * stats, write profiling info, close open files and flush buffers etc.
292 * -------------------------------------------------------------------------- */
294 pthread_t startup_guy;
298 shutdown_handler(int sig STG_UNUSED)
301 // if I'm a worker thread, send this signal to the guy who
302 // originally called startupHaskell(). Since we're handling
303 // the signal, it won't be a "send to all threads" type of signal
304 // (according to the POSIX threads spec).
305 if (pthread_self() != startup_guy) {
306 pthread_kill(startup_guy, sig);
311 // If we're already trying to interrupt the RTS, terminate with
312 // extreme prejudice. So the first ^C tries to exit the program
313 // cleanly, and the second one just kills it.
315 exit(EXIT_INTERRUPTED);
321 /* -----------------------------------------------------------------------------
322 * Install default signal handlers.
324 * The RTS installs a default signal handler for catching
325 * SIGINT, so that we can perform an orderly shutdown.
327 * Haskell code may install their own SIGINT handler, which is
328 * fine, provided they're so kind as to put back the old one
329 * when they de-install.
331 * In addition to handling SIGINT, the RTS also handles SIGFPE
332 * by ignoring it. Apparently IEEE requires floating-point
333 * exceptions to be ignored by default, but alpha-dec-osf3
334 * doesn't seem to do so.
335 * -------------------------------------------------------------------------- */
337 initDefaultHandlers()
339 struct sigaction action,oact;
342 startup_guy = pthread_self();
345 // install the SIGINT handler
346 action.sa_handler = shutdown_handler;
347 sigemptyset(&action.sa_mask);
349 if (sigaction(SIGINT, &action, &oact) != 0) {
350 prog_belch("warning: failed to install SIGINT handler");
353 siginterrupt(SIGINT, 1); // isn't this the default? --SDM
355 // install the SIGCONT handler
356 action.sa_handler = cont_handler;
357 sigemptyset(&action.sa_mask);
359 if (sigaction(SIGCONT, &action, &oact) != 0) {
360 prog_belch("warning: failed to install SIGCONT handler");
363 // install the SIGFPE handler
364 action.sa_handler = SIG_IGN;
365 sigemptyset(&action.sa_mask);
367 if (sigaction(SIGFPE, &action, &oact) != 0) {
368 prog_belch("warning: failed to install SIGFPE handler");
370 #ifdef alpha_TARGET_ARCH
371 ieee_set_fp_control(0);
375 #endif /*! mingw32_TARGET_OS */