1 /* -----------------------------------------------------------------------------
3 * (c) The GHC Team, 1998-1999
5 * Signal processing / handling.
7 * ---------------------------------------------------------------------------*/
9 /* This is non-Posix-compliant.
10 #include "PosixSource.h"
19 #ifdef alpha_HOST_ARCH
20 # if defined(linux_HOST_OS)
23 # include <machine/fpu.h>
37 /* This curious flag is provided for the benefit of the Haskell binding
38 * to POSIX.1 to control whether or not to include SA_NOCLDSTOP when
39 * installing a SIGCHLD handler.
43 /* -----------------------------------------------------------------------------
44 * The table of signal handlers
45 * -------------------------------------------------------------------------- */
47 #if defined(RTS_USER_SIGNALS)
49 /* SUP: The type of handlers is a little bit, well, doubtful... */
50 static StgInt *handlers = NULL; /* Dynamically grown array of signal handlers */
51 static StgInt nHandlers = 0; /* Size of handlers array */
53 static nat n_haskell_handlers = 0;
55 /* -----------------------------------------------------------------------------
56 * Allocate/resize the table of signal handlers.
57 * -------------------------------------------------------------------------- */
68 handlers = (StgInt *)stgMallocBytes((sig + 1) * sizeof(StgInt), "more_handlers");
70 handlers = (StgInt *)stgReallocBytes(handlers, (sig + 1) * sizeof(StgInt), "more_handlers");
72 for(i = nHandlers; i <= sig; i++)
73 // Fill in the new slots with default actions
74 handlers[i] = STG_SIG_DFL;
79 /* -----------------------------------------------------------------------------
82 * The mechanism for starting handlers differs between the threaded
83 * (RTS_SUPPORTS_THREADS) and non-threaded versions of the RTS.
85 * When the RTS is single-threaded, we just write the pending signal
86 * handlers into a buffer, and start a thread for each one in the
89 * When RTS_SUPPORTS_THREADS, the problem is that signals might be
90 * delivered to multiple threads, so we would need to synchronise
91 * access to pending_handler_buf somehow. Using thread
92 * synchronisation from a signal handler isn't possible in general
93 * (some OSs support it, eg. MacOS X, but not all). So instead:
95 * - the signal handler writes the signal number into the pipe
96 * managed by the IO manager thread (see GHC.Conc).
97 * - the IO manager picks up the signal number and calls
98 * startSignalHandler() to start the thread.
100 * This also has the nice property that we don't need to arrange to
101 * wake up a worker task to start the signal handler: the IO manager
102 * wakes up when we write into the pipe.
104 * -------------------------------------------------------------------------- */
106 // Here's the pipe into which we will send our signals
107 static int io_manager_pipe = -1;
110 setIOManagerPipe (int fd)
112 // only called when RTS_SUPPORTS_THREADS, but unconditionally
113 // compiled here because GHC.Conc depends on it.
114 io_manager_pipe = fd;
117 #if !defined(RTS_SUPPORTS_THREADS)
119 #define N_PENDING_HANDLERS 16
121 StgPtr pending_handler_buf[N_PENDING_HANDLERS];
122 StgPtr *next_pending_handler = pending_handler_buf;
124 #endif /* RTS_SUPPORTS_THREADS */
126 /* -----------------------------------------------------------------------------
129 * It seems that shells tend to put stdin back into blocking mode
130 * following a suspend/resume of the process. Here we arrange to put
131 * it back into non-blocking mode. We don't do anything to
132 * stdout/stderr because these handles don't get put into non-blocking
133 * mode at all - see the comments on stdout/stderr in PrelHandle.hsc.
134 * -------------------------------------------------------------------------- */
137 cont_handler(int sig STG_UNUSED)
142 /* -----------------------------------------------------------------------------
143 * Low-level signal handler
145 * Places the requested handler on a stack of pending handlers to be
146 * started up at the next context switch.
147 * -------------------------------------------------------------------------- */
150 generic_handler(int sig)
154 #if defined(RTS_SUPPORTS_THREADS)
156 if (io_manager_pipe != -1)
158 // Write the signal number into the pipe as a single byte. We
159 // hope that signals fit into a byte...
160 StgWord8 csig = (StgWord8)sig;
161 write(io_manager_pipe, &csig, 1);
163 // If the IO manager hasn't told us what the FD of the write end
164 // of its pipe is, there's not much we can do here, so just ignore
167 #else /* not RTS_SUPPORTS_THREADS */
169 /* Can't call allocate from here. Probably can't call malloc
170 either. However, we have to schedule a new thread somehow.
172 It's probably ok to request a context switch and allow the
173 scheduler to start the handler thread, but how do we
174 communicate this to the scheduler?
176 We need some kind of locking, but with low overhead (i.e. no
177 blocking signals every time around the scheduler).
179 Signal Handlers are atomic (i.e. they can't be interrupted), and
180 we can make use of this. We just need to make sure the
181 critical section of the scheduler can't be interrupted - the
182 only way to do this is to block signals. However, we can lower
183 the overhead by only blocking signals when there are any
184 handlers to run, i.e. the set of pending handlers is
188 /* We use a stack to store the pending signals. We can't
189 dynamically grow this since we can't allocate any memory from
190 within a signal handler.
192 Hence unfortunately we have to bomb out if the buffer
193 overflows. It might be acceptable to carry on in certain
194 circumstances, depending on the signal.
197 *next_pending_handler++ = deRefStablePtr((StgStablePtr)handlers[sig]);
200 if (next_pending_handler == &pending_handler_buf[N_PENDING_HANDLERS]) {
201 errorBelch("too many pending signals");
202 stg_exit(EXIT_FAILURE);
205 #endif /* RTS_SUPPORTS_THREADS */
207 // re-establish the signal handler, and carry on
208 sigemptyset(&signals);
209 sigaddset(&signals, sig);
210 sigprocmask(SIG_UNBLOCK, &signals, NULL);
212 // *always* do the SIGCONT handler, even if the user overrides it.
213 if (sig == SIGCONT) {
220 /* -----------------------------------------------------------------------------
221 * Blocking/Unblocking of the user signals
222 * -------------------------------------------------------------------------- */
224 static sigset_t userSignals;
225 static sigset_t savedSignals;
228 initUserSignals(void)
230 sigemptyset(&userSignals);
234 blockUserSignals(void)
236 sigprocmask(SIG_BLOCK, &userSignals, &savedSignals);
240 unblockUserSignals(void)
242 sigprocmask(SIG_SETMASK, &savedSignals, NULL);
246 anyUserHandlers(void)
248 return n_haskell_handlers != 0;
251 #if !defined(RTS_SUPPORTS_THREADS)
253 awaitUserSignals(void)
255 while (!signals_pending() && !interrupted) {
261 /* -----------------------------------------------------------------------------
262 * Install a Haskell signal handler.
263 * -------------------------------------------------------------------------- */
266 stg_sig_install(int sig, int spi, StgStablePtr *handler, void *mask)
268 sigset_t signals, osignals;
269 struct sigaction action;
272 // Block the signal until we figure out what to do
273 // Count on this to fail if the signal number is invalid
274 if (sig < 0 || sigemptyset(&signals) ||
275 sigaddset(&signals, sig) || sigprocmask(SIG_BLOCK, &signals, &osignals)) {
281 previous_spi = handlers[sig];
287 handlers[sig] = STG_SIG_IGN;
288 sigdelset(&userSignals, sig);
289 action.sa_handler = SIG_IGN;
293 handlers[sig] = STG_SIG_DFL;
294 sigdelset(&userSignals, sig);
295 action.sa_handler = SIG_DFL;
300 handlers[sig] = (StgInt)*handler;
301 sigaddset(&userSignals, sig);
302 action.sa_handler = generic_handler;
303 if (spi == STG_SIG_RST) {
304 action.sa_flags = SA_RESETHAND;
306 n_haskell_handlers++;
310 barf("stg_sig_install: bad spi");
314 action.sa_mask = *(sigset_t *)mask;
316 sigemptyset(&action.sa_mask);
318 action.sa_flags |= sig == SIGCHLD && nocldstop ? SA_NOCLDSTOP : 0;
320 if (sigaction(sig, &action, NULL) ||
321 sigprocmask(SIG_SETMASK, &osignals, NULL))
323 // need to return an error code, so avoid a stable pointer leak
324 // by freeing the previous handler if there was one.
325 if (previous_spi >= 0) {
326 freeStablePtr(stgCast(StgStablePtr,handlers[sig]));
327 n_haskell_handlers--;
332 if (previous_spi == STG_SIG_DFL || previous_spi == STG_SIG_IGN
333 || previous_spi == STG_SIG_ERR) {
336 *handler = (StgStablePtr)previous_spi;
341 /* -----------------------------------------------------------------------------
342 * Creating new threads for signal handlers.
343 * -------------------------------------------------------------------------- */
346 startSignalHandler(int sig) // called by the IO manager, see GHC.Conc
348 #if defined(RTS_SUPPORTS_THREADS)
349 // ToDo: fix race window between the time at which the signal is
350 // delivered and the deRefStablePtr() call here. There's no way
351 // to safely uninstall a signal handler.
353 createIOThread(RtsFlags.GcFlags.initialStkSize,
354 (StgClosure *)deRefStablePtr((StgStablePtr)handlers[sig]))
357 (void)sig; /* keep gcc -Wall happy */
362 startSignalHandlers(void)
364 #if !defined(RTS_SUPPORTS_THREADS)
367 while (next_pending_handler != pending_handler_buf) {
369 next_pending_handler--;
372 createIOThread(RtsFlags.GcFlags.initialStkSize,
373 (StgClosure *) *next_pending_handler));
376 unblockUserSignals();
380 /* ----------------------------------------------------------------------------
381 * Mark signal handlers during GC.
383 * We do this rather than trying to start all the signal handlers
384 * prior to GC, because that requires extra heap for the new threads.
385 * Signals must be blocked (see blockUserSignals() above) during GC to
386 * avoid race conditions.
387 * -------------------------------------------------------------------------- */
389 #if !defined(RTS_SUPPORTS_THREADS)
391 markSignalHandlers (evac_fn evac)
395 p = next_pending_handler;
396 while (p != pending_handler_buf) {
398 evac((StgClosure **)p);
403 markSignalHandlers (evac_fn evac STG_UNUSED)
408 #else /* !RTS_USER_SIGNALS */
410 stg_sig_install(StgInt sig STG_UNUSED,
411 StgInt spi STG_UNUSED,
412 StgStablePtr* handler STG_UNUSED,
413 void* mask STG_UNUSED)
415 //barf("User signals not supported");
421 #if defined(RTS_USER_SIGNALS)
422 /* -----------------------------------------------------------------------------
425 * We like to shutdown nicely after receiving a SIGINT, write out the
426 * stats, write profiling info, close open files and flush buffers etc.
427 * -------------------------------------------------------------------------- */
429 pthread_t startup_guy;
433 shutdown_handler(int sig STG_UNUSED)
436 // if I'm a worker thread, send this signal to the guy who
437 // originally called startupHaskell(). Since we're handling
438 // the signal, it won't be a "send to all threads" type of signal
439 // (according to the POSIX threads spec).
440 if (pthread_self() != startup_guy) {
441 pthread_kill(startup_guy, sig);
446 // If we're already trying to interrupt the RTS, terminate with
447 // extreme prejudice. So the first ^C tries to exit the program
448 // cleanly, and the second one just kills it.
450 stg_exit(EXIT_INTERRUPTED);
456 /* -----------------------------------------------------------------------------
457 * Install default signal handlers.
459 * The RTS installs a default signal handler for catching
460 * SIGINT, so that we can perform an orderly shutdown.
462 * Haskell code may install their own SIGINT handler, which is
463 * fine, provided they're so kind as to put back the old one
464 * when they de-install.
466 * In addition to handling SIGINT, the RTS also handles SIGFPE
467 * by ignoring it. Apparently IEEE requires floating-point
468 * exceptions to be ignored by default, but alpha-dec-osf3
469 * doesn't seem to do so.
470 * -------------------------------------------------------------------------- */
472 initDefaultHandlers()
474 struct sigaction action,oact;
477 startup_guy = pthread_self();
480 // install the SIGINT handler
481 action.sa_handler = shutdown_handler;
482 sigemptyset(&action.sa_mask);
484 if (sigaction(SIGINT, &action, &oact) != 0) {
485 errorBelch("warning: failed to install SIGINT handler");
488 #if defined(HAVE_SIGINTERRUPT)
489 siginterrupt(SIGINT, 1); // isn't this the default? --SDM
492 // install the SIGCONT handler
493 action.sa_handler = cont_handler;
494 sigemptyset(&action.sa_mask);
496 if (sigaction(SIGCONT, &action, &oact) != 0) {
497 errorBelch("warning: failed to install SIGCONT handler");
500 // install the SIGFPE handler
502 // In addition to handling SIGINT, also handle SIGFPE by ignoring it.
503 // Apparently IEEE requires floating-point exceptions to be ignored by
504 // default, but alpha-dec-osf3 doesn't seem to do so.
506 // Commented out by SDM 2/7/2002: this causes an infinite loop on
507 // some architectures when an integer division by zero occurs: we
508 // don't recover from the floating point exception, and the
509 // program just generates another one immediately.
511 action.sa_handler = SIG_IGN;
512 sigemptyset(&action.sa_mask);
514 if (sigaction(SIGFPE, &action, &oact) != 0) {
515 errorBelch("warning: failed to install SIGFPE handler");
519 #ifdef alpha_HOST_ARCH
520 ieee_set_fp_control(0);
524 #endif /* RTS_USER_SIGNALS */