1 /* -----------------------------------------------------------------------------
2 * $Id: Signals.c,v 1.35 2003/03/25 17:15:07 sof 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>
35 #ifndef mingw32_TARGET_OS
39 /* SUP: The type of handlers is a little bit, well, doubtful... */
40 static StgInt *handlers = NULL; /* Dynamically grown array of signal handlers */
41 static StgInt nHandlers = 0; /* Size of handlers array */
43 static nat n_haskell_handlers = 0;
45 #define N_PENDING_HANDLERS 16
47 StgPtr pending_handler_buf[N_PENDING_HANDLERS];
48 StgPtr *next_pending_handler = pending_handler_buf;
53 #ifdef RTS_SUPPORTS_THREADS
54 pthread_t signalHandlingThread;
57 // Handle all signals in the current thread.
58 // Called from Capability.c whenever the main capability is granted to a thread
59 // and in installDefaultHandlers
61 handleSignalsInThisThread()
63 #ifdef RTS_SUPPORTS_THREADS
64 signalHandlingThread = pthread_self();
69 /* -----------------------------------------------------------------------------
70 * Allocate/resize the table of signal handlers.
71 * -------------------------------------------------------------------------- */
82 handlers = (StgInt *)stgMallocBytes((sig + 1) * sizeof(StgInt), "more_handlers");
84 handlers = (StgInt *)stgReallocBytes(handlers, (sig + 1) * sizeof(StgInt), "more_handlers");
86 for(i = nHandlers; i <= sig; i++)
87 // Fill in the new slots with default actions
88 handlers[i] = STG_SIG_DFL;
93 /* -----------------------------------------------------------------------------
96 * It seems that shells tend to put stdin back into blocking mode
97 * following a suspend/resume of the process. Here we arrange to put
98 * it back into non-blocking mode. We don't do anything to
99 * stdout/stderr because these handles don't get put into non-blocking
100 * mode at all - see the comments on stdout/stderr in PrelHandle.hsc.
101 * -------------------------------------------------------------------------- */
104 cont_handler(int sig STG_UNUSED)
109 /* -----------------------------------------------------------------------------
110 * Low-level signal handler
112 * Places the requested handler on a stack of pending handlers to be
113 * started up at the next context switch.
114 * -------------------------------------------------------------------------- */
117 generic_handler(int sig)
121 #if defined(THREADED_RTS)
122 // Make the thread that currently holds the main capability
123 // handle the signal.
124 // This makes sure that awaitEvent() is interrupted
125 // and it (hopefully) prevents race conditions
126 // (signal handlers are not atomic with respect to other threads)
128 if(pthread_self() != signalHandlingThread) {
129 pthread_kill(signalHandlingThread, sig);
134 /* Can't call allocate from here. Probably can't call malloc
135 either. However, we have to schedule a new thread somehow.
137 It's probably ok to request a context switch and allow the
138 scheduler to start the handler thread, but how do we
139 communicate this to the scheduler?
141 We need some kind of locking, but with low overhead (i.e. no
142 blocking signals every time around the scheduler).
144 Signal Handlers are atomic (i.e. they can't be interrupted), and
145 we can make use of this. We just need to make sure the
146 critical section of the scheduler can't be interrupted - the
147 only way to do this is to block signals. However, we can lower
148 the overhead by only blocking signals when there are any
149 handlers to run, i.e. the set of pending handlers is
153 /* We use a stack to store the pending signals. We can't
154 dynamically grow this since we can't allocate any memory from
155 within a signal handler.
157 Hence unfortunately we have to bomb out if the buffer
158 overflows. It might be acceptable to carry on in certain
159 circumstances, depending on the signal.
162 *next_pending_handler++ = deRefStablePtr((StgStablePtr)handlers[sig]);
165 if (next_pending_handler == &pending_handler_buf[N_PENDING_HANDLERS]) {
166 prog_belch("too many pending signals");
167 stg_exit(EXIT_FAILURE);
170 // re-establish the signal handler, and carry on
171 sigemptyset(&signals);
172 sigaddset(&signals, sig);
173 sigprocmask(SIG_UNBLOCK, &signals, NULL);
175 // *always* do the SIGCONT handler, even if the user overrides it.
176 if (sig == SIGCONT) {
183 /* -----------------------------------------------------------------------------
184 * Blocking/Unblocking of the user signals
185 * -------------------------------------------------------------------------- */
187 static sigset_t userSignals;
188 static sigset_t savedSignals;
191 initUserSignals(void)
193 sigemptyset(&userSignals);
197 blockUserSignals(void)
199 sigprocmask(SIG_BLOCK, &userSignals, &savedSignals);
203 unblockUserSignals(void)
205 sigprocmask(SIG_SETMASK, &savedSignals, NULL);
209 anyUserHandlers(void)
211 return n_haskell_handlers != 0;
215 awaitUserSignals(void)
217 while (!signals_pending() && !interrupted) {
222 /* -----------------------------------------------------------------------------
223 * Install a Haskell signal handler.
224 * -------------------------------------------------------------------------- */
227 stg_sig_install(int sig, int spi, StgStablePtr *handler, void *mask)
229 sigset_t signals, osignals;
230 struct sigaction action;
233 // Block the signal until we figure out what to do
234 // Count on this to fail if the signal number is invalid
235 if (sig < 0 || sigemptyset(&signals) ||
236 sigaddset(&signals, sig) || sigprocmask(SIG_BLOCK, &signals, &osignals)) {
242 previous_spi = handlers[sig];
248 handlers[sig] = STG_SIG_IGN;
249 sigdelset(&userSignals, sig);
250 action.sa_handler = SIG_IGN;
254 handlers[sig] = STG_SIG_DFL;
255 sigdelset(&userSignals, sig);
256 action.sa_handler = SIG_DFL;
261 handlers[sig] = (StgInt)*handler;
262 sigaddset(&userSignals, sig);
263 action.sa_handler = generic_handler;
264 if (spi == STG_SIG_RST) {
265 action.sa_flags = SA_RESETHAND;
267 n_haskell_handlers++;
271 barf("stg_sig_install: bad spi");
275 action.sa_mask = *(sigset_t *)mask;
277 sigemptyset(&action.sa_mask);
279 action.sa_flags |= sig == SIGCHLD && nocldstop ? SA_NOCLDSTOP : 0;
281 if (sigaction(sig, &action, NULL) ||
282 sigprocmask(SIG_SETMASK, &osignals, NULL))
284 // need to return an error code, so avoid a stable pointer leak
285 // by freeing the previous handler if there was one.
286 if (previous_spi >= 0) {
287 freeStablePtr(stgCast(StgStablePtr,handlers[sig]));
288 n_haskell_handlers--;
293 if (previous_spi == STG_SIG_DFL || previous_spi == STG_SIG_IGN
294 || previous_spi == STG_SIG_ERR) {
297 *handler = (StgStablePtr)previous_spi;
302 /* -----------------------------------------------------------------------------
303 * Creating new threads for the pending signal handlers.
304 * -------------------------------------------------------------------------- */
306 startSignalHandlers(void)
310 while (next_pending_handler != pending_handler_buf) {
312 next_pending_handler--;
315 createIOThread(RtsFlags.GcFlags.initialStkSize,
316 (StgClosure *) *next_pending_handler));
319 unblockUserSignals();
322 /* ----------------------------------------------------------------------------
323 * Mark signal handlers during GC.
325 * We do this rather than trying to start all the signal handlers
326 * prior to GC, because that requires extra heap for the new threads.
327 * Signals must be blocked (see blockUserSignals() above) during GC to
328 * avoid race conditions.
329 * -------------------------------------------------------------------------- */
332 markSignalHandlers (evac_fn evac)
336 p = next_pending_handler;
337 while (p != pending_handler_buf) {
339 evac((StgClosure **)p);
345 stg_sig_install(StgInt sig, StgInt spi, StgStablePtr handler, sigset_t *mask)
347 // don't fflush(stdout); WORKAROUND bug in Linux glibc
348 barf("no signal handling support in a parallel implementation");
352 startSignalHandlers(void)
357 /* -----------------------------------------------------------------------------
360 * We like to shutdown nicely after receiving a SIGINT, write out the
361 * stats, write profiling info, close open files and flush buffers etc.
362 * -------------------------------------------------------------------------- */
364 pthread_t startup_guy;
368 shutdown_handler(int sig STG_UNUSED)
371 // if I'm a worker thread, send this signal to the guy who
372 // originally called startupHaskell(). Since we're handling
373 // the signal, it won't be a "send to all threads" type of signal
374 // (according to the POSIX threads spec).
375 if (pthread_self() != startup_guy) {
376 pthread_kill(startup_guy, sig);
379 // ToDo: The code for the threaded RTS below does something very
380 // similar. Maybe the SMP special case is not needed
381 // -- Wolfgang Thaller
382 #elif defined(THREADED_RTS)
383 // Make the thread that currently holds the main capability
384 // handle the signal.
385 // This makes sure that awaitEvent() is interrupted
386 if(pthread_self() != signalHandlingThread) {
387 pthread_kill(signalHandlingThread, sig);
392 // If we're already trying to interrupt the RTS, terminate with
393 // extreme prejudice. So the first ^C tries to exit the program
394 // cleanly, and the second one just kills it.
396 stg_exit(EXIT_INTERRUPTED);
402 /* -----------------------------------------------------------------------------
403 * Install default signal handlers.
405 * The RTS installs a default signal handler for catching
406 * SIGINT, so that we can perform an orderly shutdown.
408 * Haskell code may install their own SIGINT handler, which is
409 * fine, provided they're so kind as to put back the old one
410 * when they de-install.
412 * In addition to handling SIGINT, the RTS also handles SIGFPE
413 * by ignoring it. Apparently IEEE requires floating-point
414 * exceptions to be ignored by default, but alpha-dec-osf3
415 * doesn't seem to do so.
416 * -------------------------------------------------------------------------- */
418 initDefaultHandlers()
420 struct sigaction action,oact;
423 startup_guy = pthread_self();
425 #ifdef RTS_SUPPORTS_THREADS
426 handleSignalsInThisThread();
429 // install the SIGINT handler
430 action.sa_handler = shutdown_handler;
431 sigemptyset(&action.sa_mask);
433 if (sigaction(SIGINT, &action, &oact) != 0) {
434 prog_belch("warning: failed to install SIGINT handler");
437 #ifndef cygwin32_TARGET_OS
438 siginterrupt(SIGINT, 1); // isn't this the default? --SDM
441 // install the SIGCONT handler
442 action.sa_handler = cont_handler;
443 sigemptyset(&action.sa_mask);
445 if (sigaction(SIGCONT, &action, &oact) != 0) {
446 prog_belch("warning: failed to install SIGCONT handler");
449 // install the SIGFPE handler
451 // In addition to handling SIGINT, also handle SIGFPE by ignoring it.
452 // Apparently IEEE requires floating-point exceptions to be ignored by
453 // default, but alpha-dec-osf3 doesn't seem to do so.
455 // Commented out by SDM 2/7/2002: this causes an infinite loop on
456 // some architectures when an integer division by zero occurs: we
457 // don't recover from the floating point exception, and the
458 // program just generates another one immediately.
460 action.sa_handler = SIG_IGN;
461 sigemptyset(&action.sa_mask);
463 if (sigaction(SIGFPE, &action, &oact) != 0) {
464 prog_belch("warning: failed to install SIGFPE handler");
468 #ifdef alpha_TARGET_ARCH
469 ieee_set_fp_control(0);
472 #else /* mingw32_TARGET_OS */
474 // Handle all signals in the current thread.
475 // Called from Capability.c whenever the main capability is granted to a thread
476 // and in installDefaultHandlers
478 handleSignalsInThisThread()
480 #ifdef RTS_SUPPORTS_THREADS
481 #error "handleSignalsInThread needs to be sorted out for MinGW32"
482 /* signalHandlingThread = pthread_self();*/
486 #endif /* mingw32_TARGET_OS */