1 /* -----------------------------------------------------------------------------
2 * $Id: Signals.c,v 1.40 2003/10/31 23:24:47 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 # if defined(linux_TARGET_OS)
25 # include <machine/fpu.h>
39 /* This curious flag is provided for the benefit of the Haskell binding
40 * to POSIX.1 to control whether or not to include SA_NOCLDSTOP when
41 * installing a SIGCHLD handler.
46 #if defined(RTS_USER_SIGNALS)
48 /* SUP: The type of handlers is a little bit, well, doubtful... */
49 static StgInt *handlers = NULL; /* Dynamically grown array of signal handlers */
50 static StgInt nHandlers = 0; /* Size of handlers array */
52 static nat n_haskell_handlers = 0;
54 #define N_PENDING_HANDLERS 16
56 StgPtr pending_handler_buf[N_PENDING_HANDLERS];
57 StgPtr *next_pending_handler = pending_handler_buf;
59 #ifdef RTS_SUPPORTS_THREADS
60 pthread_t signalHandlingThread;
63 // Handle all signals in the current thread.
64 // Called from Capability.c whenever the main capability is granted to a thread
65 // and in installDefaultHandlers
67 handleSignalsInThisThread()
69 #ifdef RTS_SUPPORTS_THREADS
70 signalHandlingThread = pthread_self();
75 /* -----------------------------------------------------------------------------
76 * Allocate/resize the table of signal handlers.
77 * -------------------------------------------------------------------------- */
88 handlers = (StgInt *)stgMallocBytes((sig + 1) * sizeof(StgInt), "more_handlers");
90 handlers = (StgInt *)stgReallocBytes(handlers, (sig + 1) * sizeof(StgInt), "more_handlers");
92 for(i = nHandlers; i <= sig; i++)
93 // Fill in the new slots with default actions
94 handlers[i] = STG_SIG_DFL;
99 /* -----------------------------------------------------------------------------
102 * It seems that shells tend to put stdin back into blocking mode
103 * following a suspend/resume of the process. Here we arrange to put
104 * it back into non-blocking mode. We don't do anything to
105 * stdout/stderr because these handles don't get put into non-blocking
106 * mode at all - see the comments on stdout/stderr in PrelHandle.hsc.
107 * -------------------------------------------------------------------------- */
110 cont_handler(int sig STG_UNUSED)
115 /* -----------------------------------------------------------------------------
116 * Low-level signal handler
118 * Places the requested handler on a stack of pending handlers to be
119 * started up at the next context switch.
120 * -------------------------------------------------------------------------- */
123 generic_handler(int sig)
127 #if defined(THREADED_RTS)
128 // Make the thread that currently holds the main capability
129 // handle the signal.
130 // This makes sure that awaitEvent() is interrupted
131 // and it (hopefully) prevents race conditions
132 // (signal handlers are not atomic with respect to other threads)
134 if(pthread_self() != signalHandlingThread) {
135 pthread_kill(signalHandlingThread, sig);
140 /* Can't call allocate from here. Probably can't call malloc
141 either. However, we have to schedule a new thread somehow.
143 It's probably ok to request a context switch and allow the
144 scheduler to start the handler thread, but how do we
145 communicate this to the scheduler?
147 We need some kind of locking, but with low overhead (i.e. no
148 blocking signals every time around the scheduler).
150 Signal Handlers are atomic (i.e. they can't be interrupted), and
151 we can make use of this. We just need to make sure the
152 critical section of the scheduler can't be interrupted - the
153 only way to do this is to block signals. However, we can lower
154 the overhead by only blocking signals when there are any
155 handlers to run, i.e. the set of pending handlers is
159 /* We use a stack to store the pending signals. We can't
160 dynamically grow this since we can't allocate any memory from
161 within a signal handler.
163 Hence unfortunately we have to bomb out if the buffer
164 overflows. It might be acceptable to carry on in certain
165 circumstances, depending on the signal.
168 *next_pending_handler++ = deRefStablePtr((StgStablePtr)handlers[sig]);
171 if (next_pending_handler == &pending_handler_buf[N_PENDING_HANDLERS]) {
172 prog_belch("too many pending signals");
173 stg_exit(EXIT_FAILURE);
176 // re-establish the signal handler, and carry on
177 sigemptyset(&signals);
178 sigaddset(&signals, sig);
179 sigprocmask(SIG_UNBLOCK, &signals, NULL);
181 // *always* do the SIGCONT handler, even if the user overrides it.
182 if (sig == SIGCONT) {
189 /* -----------------------------------------------------------------------------
190 * Blocking/Unblocking of the user signals
191 * -------------------------------------------------------------------------- */
193 static sigset_t userSignals;
194 static sigset_t savedSignals;
197 initUserSignals(void)
199 sigemptyset(&userSignals);
203 blockUserSignals(void)
205 sigprocmask(SIG_BLOCK, &userSignals, &savedSignals);
209 unblockUserSignals(void)
211 sigprocmask(SIG_SETMASK, &savedSignals, NULL);
215 anyUserHandlers(void)
217 return n_haskell_handlers != 0;
221 awaitUserSignals(void)
223 while (!signals_pending() && !interrupted) {
228 /* -----------------------------------------------------------------------------
229 * Install a Haskell signal handler.
230 * -------------------------------------------------------------------------- */
233 stg_sig_install(int sig, int spi, StgStablePtr *handler, void *mask)
235 sigset_t signals, osignals;
236 struct sigaction action;
239 // Block the signal until we figure out what to do
240 // Count on this to fail if the signal number is invalid
241 if (sig < 0 || sigemptyset(&signals) ||
242 sigaddset(&signals, sig) || sigprocmask(SIG_BLOCK, &signals, &osignals)) {
248 previous_spi = handlers[sig];
254 handlers[sig] = STG_SIG_IGN;
255 sigdelset(&userSignals, sig);
256 action.sa_handler = SIG_IGN;
260 handlers[sig] = STG_SIG_DFL;
261 sigdelset(&userSignals, sig);
262 action.sa_handler = SIG_DFL;
267 handlers[sig] = (StgInt)*handler;
268 sigaddset(&userSignals, sig);
269 action.sa_handler = generic_handler;
270 if (spi == STG_SIG_RST) {
271 action.sa_flags = SA_RESETHAND;
273 n_haskell_handlers++;
277 barf("stg_sig_install: bad spi");
281 action.sa_mask = *(sigset_t *)mask;
283 sigemptyset(&action.sa_mask);
285 action.sa_flags |= sig == SIGCHLD && nocldstop ? SA_NOCLDSTOP : 0;
287 if (sigaction(sig, &action, NULL) ||
288 sigprocmask(SIG_SETMASK, &osignals, NULL))
290 // need to return an error code, so avoid a stable pointer leak
291 // by freeing the previous handler if there was one.
292 if (previous_spi >= 0) {
293 freeStablePtr(stgCast(StgStablePtr,handlers[sig]));
294 n_haskell_handlers--;
299 if (previous_spi == STG_SIG_DFL || previous_spi == STG_SIG_IGN
300 || previous_spi == STG_SIG_ERR) {
303 *handler = (StgStablePtr)previous_spi;
308 /* -----------------------------------------------------------------------------
309 * Creating new threads for the pending signal handlers.
310 * -------------------------------------------------------------------------- */
312 startSignalHandlers(void)
316 while (next_pending_handler != pending_handler_buf) {
318 next_pending_handler--;
321 createIOThread(RtsFlags.GcFlags.initialStkSize,
322 (StgClosure *) *next_pending_handler));
325 unblockUserSignals();
328 /* ----------------------------------------------------------------------------
329 * Mark signal handlers during GC.
331 * We do this rather than trying to start all the signal handlers
332 * prior to GC, because that requires extra heap for the new threads.
333 * Signals must be blocked (see blockUserSignals() above) during GC to
334 * avoid race conditions.
335 * -------------------------------------------------------------------------- */
338 markSignalHandlers (evac_fn evac)
342 p = next_pending_handler;
343 while (p != pending_handler_buf) {
345 evac((StgClosure **)p);
349 #else /* !RTS_USER_SIGNALS */
351 stg_sig_install(StgInt sig STG_UNUSED,
352 StgInt spi STG_UNUSED,
353 StgStablePtr* handler STG_UNUSED,
354 void* mask STG_UNUSED)
356 //barf("User signals not supported");
362 #if defined(RTS_USER_SIGNALS)
363 /* -----------------------------------------------------------------------------
366 * We like to shutdown nicely after receiving a SIGINT, write out the
367 * stats, write profiling info, close open files and flush buffers etc.
368 * -------------------------------------------------------------------------- */
370 pthread_t startup_guy;
374 shutdown_handler(int sig STG_UNUSED)
377 // if I'm a worker thread, send this signal to the guy who
378 // originally called startupHaskell(). Since we're handling
379 // the signal, it won't be a "send to all threads" type of signal
380 // (according to the POSIX threads spec).
381 if (pthread_self() != startup_guy) {
382 pthread_kill(startup_guy, sig);
385 // ToDo: The code for the threaded RTS below does something very
386 // similar. Maybe the SMP special case is not needed
387 // -- Wolfgang Thaller
388 #elif defined(THREADED_RTS)
389 // Make the thread that currently holds the main capability
390 // handle the signal.
391 // This makes sure that awaitEvent() is interrupted
392 if(pthread_self() != signalHandlingThread) {
393 pthread_kill(signalHandlingThread, sig);
398 // If we're already trying to interrupt the RTS, terminate with
399 // extreme prejudice. So the first ^C tries to exit the program
400 // cleanly, and the second one just kills it.
402 stg_exit(EXIT_INTERRUPTED);
408 /* -----------------------------------------------------------------------------
409 * Install default signal handlers.
411 * The RTS installs a default signal handler for catching
412 * SIGINT, so that we can perform an orderly shutdown.
414 * Haskell code may install their own SIGINT handler, which is
415 * fine, provided they're so kind as to put back the old one
416 * when they de-install.
418 * In addition to handling SIGINT, the RTS also handles SIGFPE
419 * by ignoring it. Apparently IEEE requires floating-point
420 * exceptions to be ignored by default, but alpha-dec-osf3
421 * doesn't seem to do so.
422 * -------------------------------------------------------------------------- */
424 initDefaultHandlers()
426 struct sigaction action,oact;
429 startup_guy = pthread_self();
431 #ifdef RTS_SUPPORTS_THREADS
432 handleSignalsInThisThread();
435 // install the SIGINT handler
436 action.sa_handler = shutdown_handler;
437 sigemptyset(&action.sa_mask);
439 if (sigaction(SIGINT, &action, &oact) != 0) {
440 prog_belch("warning: failed to install SIGINT handler");
443 #if defined(HAVE_SIGINTERRUPT)
444 siginterrupt(SIGINT, 1); // isn't this the default? --SDM
447 // install the SIGCONT handler
448 action.sa_handler = cont_handler;
449 sigemptyset(&action.sa_mask);
451 if (sigaction(SIGCONT, &action, &oact) != 0) {
452 prog_belch("warning: failed to install SIGCONT handler");
455 // install the SIGFPE handler
457 // In addition to handling SIGINT, also handle SIGFPE by ignoring it.
458 // Apparently IEEE requires floating-point exceptions to be ignored by
459 // default, but alpha-dec-osf3 doesn't seem to do so.
461 // Commented out by SDM 2/7/2002: this causes an infinite loop on
462 // some architectures when an integer division by zero occurs: we
463 // don't recover from the floating point exception, and the
464 // program just generates another one immediately.
466 action.sa_handler = SIG_IGN;
467 sigemptyset(&action.sa_mask);
469 if (sigaction(SIGFPE, &action, &oact) != 0) {
470 prog_belch("warning: failed to install SIGFPE handler");
474 #ifdef alpha_TARGET_ARCH
475 ieee_set_fp_control(0);
479 #endif /* RTS_USER_SIGNALS */