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_TARGET_ARCH
20 # if defined(linux_TARGET_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.
44 #if defined(RTS_USER_SIGNALS)
46 /* SUP: The type of handlers is a little bit, well, doubtful... */
47 static StgInt *handlers = NULL; /* Dynamically grown array of signal handlers */
48 static StgInt nHandlers = 0; /* Size of handlers array */
50 static nat n_haskell_handlers = 0;
52 #define N_PENDING_HANDLERS 16
54 StgPtr pending_handler_buf[N_PENDING_HANDLERS];
55 StgPtr *next_pending_handler = pending_handler_buf;
57 /* -----------------------------------------------------------------------------
59 * -------------------------------------------------------------------------- */
61 #ifdef RTS_SUPPORTS_THREADS
62 pthread_t signalHandlingThread;
65 // Handle all signals in the current thread.
66 // Called from Capability.c whenever the main capability is granted to a thread
67 // and in installDefaultHandlers
69 handleSignalsInThisThread(void)
71 #ifdef RTS_SUPPORTS_THREADS
72 signalHandlingThread = pthread_self();
76 /* -----------------------------------------------------------------------------
77 * Allocate/resize the table of signal handlers.
78 * -------------------------------------------------------------------------- */
89 handlers = (StgInt *)stgMallocBytes((sig + 1) * sizeof(StgInt), "more_handlers");
91 handlers = (StgInt *)stgReallocBytes(handlers, (sig + 1) * sizeof(StgInt), "more_handlers");
93 for(i = nHandlers; i <= sig; i++)
94 // Fill in the new slots with default actions
95 handlers[i] = STG_SIG_DFL;
100 /* -----------------------------------------------------------------------------
103 * It seems that shells tend to put stdin back into blocking mode
104 * following a suspend/resume of the process. Here we arrange to put
105 * it back into non-blocking mode. We don't do anything to
106 * stdout/stderr because these handles don't get put into non-blocking
107 * mode at all - see the comments on stdout/stderr in PrelHandle.hsc.
108 * -------------------------------------------------------------------------- */
111 cont_handler(int sig STG_UNUSED)
116 /* -----------------------------------------------------------------------------
117 * Low-level signal handler
119 * Places the requested handler on a stack of pending handlers to be
120 * started up at the next context switch.
121 * -------------------------------------------------------------------------- */
124 generic_handler(int sig)
128 #if defined(THREADED_RTS)
129 // Make the thread that currently holds the main capability
130 // handle the signal.
131 // This makes sure that awaitEvent() is interrupted
132 // and it (hopefully) prevents race conditions
133 // (signal handlers are not atomic with respect to other threads)
135 if(pthread_self() != signalHandlingThread) {
136 pthread_kill(signalHandlingThread, sig);
141 /* Can't call allocate from here. Probably can't call malloc
142 either. However, we have to schedule a new thread somehow.
144 It's probably ok to request a context switch and allow the
145 scheduler to start the handler thread, but how do we
146 communicate this to the scheduler?
148 We need some kind of locking, but with low overhead (i.e. no
149 blocking signals every time around the scheduler).
151 Signal Handlers are atomic (i.e. they can't be interrupted), and
152 we can make use of this. We just need to make sure the
153 critical section of the scheduler can't be interrupted - the
154 only way to do this is to block signals. However, we can lower
155 the overhead by only blocking signals when there are any
156 handlers to run, i.e. the set of pending handlers is
160 /* We use a stack to store the pending signals. We can't
161 dynamically grow this since we can't allocate any memory from
162 within a signal handler.
164 Hence unfortunately we have to bomb out if the buffer
165 overflows. It might be acceptable to carry on in certain
166 circumstances, depending on the signal.
169 *next_pending_handler++ = deRefStablePtr((StgStablePtr)handlers[sig]);
172 if (next_pending_handler == &pending_handler_buf[N_PENDING_HANDLERS]) {
173 errorBelch("too many pending signals");
174 stg_exit(EXIT_FAILURE);
177 // re-establish the signal handler, and carry on
178 sigemptyset(&signals);
179 sigaddset(&signals, sig);
180 sigprocmask(SIG_UNBLOCK, &signals, NULL);
182 // *always* do the SIGCONT handler, even if the user overrides it.
183 if (sig == SIGCONT) {
190 /* -----------------------------------------------------------------------------
191 * Blocking/Unblocking of the user signals
192 * -------------------------------------------------------------------------- */
194 static sigset_t userSignals;
195 static sigset_t savedSignals;
198 initUserSignals(void)
200 sigemptyset(&userSignals);
204 blockUserSignals(void)
206 sigprocmask(SIG_BLOCK, &userSignals, &savedSignals);
210 unblockUserSignals(void)
212 sigprocmask(SIG_SETMASK, &savedSignals, NULL);
216 anyUserHandlers(void)
218 return n_haskell_handlers != 0;
222 awaitUserSignals(void)
224 while (!signals_pending() && !interrupted) {
229 /* -----------------------------------------------------------------------------
230 * Install a Haskell signal handler.
231 * -------------------------------------------------------------------------- */
234 stg_sig_install(int sig, int spi, StgStablePtr *handler, void *mask)
236 sigset_t signals, osignals;
237 struct sigaction action;
240 // Block the signal until we figure out what to do
241 // Count on this to fail if the signal number is invalid
242 if (sig < 0 || sigemptyset(&signals) ||
243 sigaddset(&signals, sig) || sigprocmask(SIG_BLOCK, &signals, &osignals)) {
249 previous_spi = handlers[sig];
255 handlers[sig] = STG_SIG_IGN;
256 sigdelset(&userSignals, sig);
257 action.sa_handler = SIG_IGN;
261 handlers[sig] = STG_SIG_DFL;
262 sigdelset(&userSignals, sig);
263 action.sa_handler = SIG_DFL;
268 handlers[sig] = (StgInt)*handler;
269 sigaddset(&userSignals, sig);
270 action.sa_handler = generic_handler;
271 if (spi == STG_SIG_RST) {
272 action.sa_flags = SA_RESETHAND;
274 n_haskell_handlers++;
278 barf("stg_sig_install: bad spi");
282 action.sa_mask = *(sigset_t *)mask;
284 sigemptyset(&action.sa_mask);
286 action.sa_flags |= sig == SIGCHLD && nocldstop ? SA_NOCLDSTOP : 0;
288 if (sigaction(sig, &action, NULL) ||
289 sigprocmask(SIG_SETMASK, &osignals, NULL))
291 // need to return an error code, so avoid a stable pointer leak
292 // by freeing the previous handler if there was one.
293 if (previous_spi >= 0) {
294 freeStablePtr(stgCast(StgStablePtr,handlers[sig]));
295 n_haskell_handlers--;
300 if (previous_spi == STG_SIG_DFL || previous_spi == STG_SIG_IGN
301 || previous_spi == STG_SIG_ERR) {
304 *handler = (StgStablePtr)previous_spi;
309 /* -----------------------------------------------------------------------------
310 * Creating new threads for the pending signal handlers.
311 * -------------------------------------------------------------------------- */
313 startSignalHandlers(void)
317 while (next_pending_handler != pending_handler_buf) {
319 next_pending_handler--;
322 createIOThread(RtsFlags.GcFlags.initialStkSize,
323 (StgClosure *) *next_pending_handler));
326 unblockUserSignals();
329 /* ----------------------------------------------------------------------------
330 * Mark signal handlers during GC.
332 * We do this rather than trying to start all the signal handlers
333 * prior to GC, because that requires extra heap for the new threads.
334 * Signals must be blocked (see blockUserSignals() above) during GC to
335 * avoid race conditions.
336 * -------------------------------------------------------------------------- */
339 markSignalHandlers (evac_fn evac)
343 p = next_pending_handler;
344 while (p != pending_handler_buf) {
346 evac((StgClosure **)p);
350 #else /* !RTS_USER_SIGNALS */
352 stg_sig_install(StgInt sig STG_UNUSED,
353 StgInt spi STG_UNUSED,
354 StgStablePtr* handler STG_UNUSED,
355 void* mask STG_UNUSED)
357 //barf("User signals not supported");
363 #if defined(RTS_USER_SIGNALS)
364 /* -----------------------------------------------------------------------------
367 * We like to shutdown nicely after receiving a SIGINT, write out the
368 * stats, write profiling info, close open files and flush buffers etc.
369 * -------------------------------------------------------------------------- */
371 pthread_t startup_guy;
375 shutdown_handler(int sig STG_UNUSED)
378 // if I'm a worker thread, send this signal to the guy who
379 // originally called startupHaskell(). Since we're handling
380 // the signal, it won't be a "send to all threads" type of signal
381 // (according to the POSIX threads spec).
382 if (pthread_self() != startup_guy) {
383 pthread_kill(startup_guy, sig);
386 // ToDo: The code for the threaded RTS below does something very
387 // similar. Maybe the SMP special case is not needed
388 // -- Wolfgang Thaller
389 #elif defined(THREADED_RTS)
390 // Make the thread that currently holds the main capability
391 // handle the signal.
392 // This makes sure that awaitEvent() is interrupted
393 if(pthread_self() != signalHandlingThread) {
394 pthread_kill(signalHandlingThread, sig);
399 // If we're already trying to interrupt the RTS, terminate with
400 // extreme prejudice. So the first ^C tries to exit the program
401 // cleanly, and the second one just kills it.
403 stg_exit(EXIT_INTERRUPTED);
409 /* -----------------------------------------------------------------------------
410 * Install default signal handlers.
412 * The RTS installs a default signal handler for catching
413 * SIGINT, so that we can perform an orderly shutdown.
415 * Haskell code may install their own SIGINT handler, which is
416 * fine, provided they're so kind as to put back the old one
417 * when they de-install.
419 * In addition to handling SIGINT, the RTS also handles SIGFPE
420 * by ignoring it. Apparently IEEE requires floating-point
421 * exceptions to be ignored by default, but alpha-dec-osf3
422 * doesn't seem to do so.
423 * -------------------------------------------------------------------------- */
425 initDefaultHandlers()
427 struct sigaction action,oact;
430 startup_guy = pthread_self();
432 #ifdef RTS_SUPPORTS_THREADS
433 handleSignalsInThisThread();
436 // install the SIGINT handler
437 action.sa_handler = shutdown_handler;
438 sigemptyset(&action.sa_mask);
440 if (sigaction(SIGINT, &action, &oact) != 0) {
441 errorBelch("warning: failed to install SIGINT handler");
444 #if defined(HAVE_SIGINTERRUPT)
445 siginterrupt(SIGINT, 1); // isn't this the default? --SDM
448 // install the SIGCONT handler
449 action.sa_handler = cont_handler;
450 sigemptyset(&action.sa_mask);
452 if (sigaction(SIGCONT, &action, &oact) != 0) {
453 errorBelch("warning: failed to install SIGCONT handler");
456 // install the SIGFPE handler
458 // In addition to handling SIGINT, also handle SIGFPE by ignoring it.
459 // Apparently IEEE requires floating-point exceptions to be ignored by
460 // default, but alpha-dec-osf3 doesn't seem to do so.
462 // Commented out by SDM 2/7/2002: this causes an infinite loop on
463 // some architectures when an integer division by zero occurs: we
464 // don't recover from the floating point exception, and the
465 // program just generates another one immediately.
467 action.sa_handler = SIG_IGN;
468 sigemptyset(&action.sa_mask);
470 if (sigaction(SIGFPE, &action, &oact) != 0) {
471 errorBelch("warning: failed to install SIGFPE handler");
475 #ifdef alpha_TARGET_ARCH
476 ieee_set_fp_control(0);
480 #endif /* RTS_USER_SIGNALS */