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 #ifdef RTS_SUPPORTS_THREADS
58 pthread_t signalHandlingThread;
61 // Handle all signals in the current thread.
62 // Called from Capability.c whenever the main capability is granted to a thread
63 // and in installDefaultHandlers
65 handleSignalsInThisThread()
67 #ifdef RTS_SUPPORTS_THREADS
68 signalHandlingThread = pthread_self();
73 /* -----------------------------------------------------------------------------
74 * Allocate/resize the table of signal handlers.
75 * -------------------------------------------------------------------------- */
86 handlers = (StgInt *)stgMallocBytes((sig + 1) * sizeof(StgInt), "more_handlers");
88 handlers = (StgInt *)stgReallocBytes(handlers, (sig + 1) * sizeof(StgInt), "more_handlers");
90 for(i = nHandlers; i <= sig; i++)
91 // Fill in the new slots with default actions
92 handlers[i] = STG_SIG_DFL;
97 /* -----------------------------------------------------------------------------
100 * It seems that shells tend to put stdin back into blocking mode
101 * following a suspend/resume of the process. Here we arrange to put
102 * it back into non-blocking mode. We don't do anything to
103 * stdout/stderr because these handles don't get put into non-blocking
104 * mode at all - see the comments on stdout/stderr in PrelHandle.hsc.
105 * -------------------------------------------------------------------------- */
108 cont_handler(int sig STG_UNUSED)
113 /* -----------------------------------------------------------------------------
114 * Low-level signal handler
116 * Places the requested handler on a stack of pending handlers to be
117 * started up at the next context switch.
118 * -------------------------------------------------------------------------- */
121 generic_handler(int sig)
125 #if defined(THREADED_RTS)
126 // Make the thread that currently holds the main capability
127 // handle the signal.
128 // This makes sure that awaitEvent() is interrupted
129 // and it (hopefully) prevents race conditions
130 // (signal handlers are not atomic with respect to other threads)
132 if(pthread_self() != signalHandlingThread) {
133 pthread_kill(signalHandlingThread, sig);
138 /* Can't call allocate from here. Probably can't call malloc
139 either. However, we have to schedule a new thread somehow.
141 It's probably ok to request a context switch and allow the
142 scheduler to start the handler thread, but how do we
143 communicate this to the scheduler?
145 We need some kind of locking, but with low overhead (i.e. no
146 blocking signals every time around the scheduler).
148 Signal Handlers are atomic (i.e. they can't be interrupted), and
149 we can make use of this. We just need to make sure the
150 critical section of the scheduler can't be interrupted - the
151 only way to do this is to block signals. However, we can lower
152 the overhead by only blocking signals when there are any
153 handlers to run, i.e. the set of pending handlers is
157 /* We use a stack to store the pending signals. We can't
158 dynamically grow this since we can't allocate any memory from
159 within a signal handler.
161 Hence unfortunately we have to bomb out if the buffer
162 overflows. It might be acceptable to carry on in certain
163 circumstances, depending on the signal.
166 *next_pending_handler++ = deRefStablePtr((StgStablePtr)handlers[sig]);
169 if (next_pending_handler == &pending_handler_buf[N_PENDING_HANDLERS]) {
170 errorBelch("too many pending signals");
171 stg_exit(EXIT_FAILURE);
174 // re-establish the signal handler, and carry on
175 sigemptyset(&signals);
176 sigaddset(&signals, sig);
177 sigprocmask(SIG_UNBLOCK, &signals, NULL);
179 // *always* do the SIGCONT handler, even if the user overrides it.
180 if (sig == SIGCONT) {
187 /* -----------------------------------------------------------------------------
188 * Blocking/Unblocking of the user signals
189 * -------------------------------------------------------------------------- */
191 static sigset_t userSignals;
192 static sigset_t savedSignals;
195 initUserSignals(void)
197 sigemptyset(&userSignals);
201 blockUserSignals(void)
203 sigprocmask(SIG_BLOCK, &userSignals, &savedSignals);
207 unblockUserSignals(void)
209 sigprocmask(SIG_SETMASK, &savedSignals, NULL);
213 anyUserHandlers(void)
215 return n_haskell_handlers != 0;
219 awaitUserSignals(void)
221 while (!signals_pending() && !interrupted) {
226 /* -----------------------------------------------------------------------------
227 * Install a Haskell signal handler.
228 * -------------------------------------------------------------------------- */
231 stg_sig_install(int sig, int spi, StgStablePtr *handler, void *mask)
233 sigset_t signals, osignals;
234 struct sigaction action;
237 // Block the signal until we figure out what to do
238 // Count on this to fail if the signal number is invalid
239 if (sig < 0 || sigemptyset(&signals) ||
240 sigaddset(&signals, sig) || sigprocmask(SIG_BLOCK, &signals, &osignals)) {
246 previous_spi = handlers[sig];
252 handlers[sig] = STG_SIG_IGN;
253 sigdelset(&userSignals, sig);
254 action.sa_handler = SIG_IGN;
258 handlers[sig] = STG_SIG_DFL;
259 sigdelset(&userSignals, sig);
260 action.sa_handler = SIG_DFL;
265 handlers[sig] = (StgInt)*handler;
266 sigaddset(&userSignals, sig);
267 action.sa_handler = generic_handler;
268 if (spi == STG_SIG_RST) {
269 action.sa_flags = SA_RESETHAND;
271 n_haskell_handlers++;
275 barf("stg_sig_install: bad spi");
279 action.sa_mask = *(sigset_t *)mask;
281 sigemptyset(&action.sa_mask);
283 action.sa_flags |= sig == SIGCHLD && nocldstop ? SA_NOCLDSTOP : 0;
285 if (sigaction(sig, &action, NULL) ||
286 sigprocmask(SIG_SETMASK, &osignals, NULL))
288 // need to return an error code, so avoid a stable pointer leak
289 // by freeing the previous handler if there was one.
290 if (previous_spi >= 0) {
291 freeStablePtr(stgCast(StgStablePtr,handlers[sig]));
292 n_haskell_handlers--;
297 if (previous_spi == STG_SIG_DFL || previous_spi == STG_SIG_IGN
298 || previous_spi == STG_SIG_ERR) {
301 *handler = (StgStablePtr)previous_spi;
306 /* -----------------------------------------------------------------------------
307 * Creating new threads for the pending signal handlers.
308 * -------------------------------------------------------------------------- */
310 startSignalHandlers(void)
314 while (next_pending_handler != pending_handler_buf) {
316 next_pending_handler--;
319 createIOThread(RtsFlags.GcFlags.initialStkSize,
320 (StgClosure *) *next_pending_handler));
323 unblockUserSignals();
326 /* ----------------------------------------------------------------------------
327 * Mark signal handlers during GC.
329 * We do this rather than trying to start all the signal handlers
330 * prior to GC, because that requires extra heap for the new threads.
331 * Signals must be blocked (see blockUserSignals() above) during GC to
332 * avoid race conditions.
333 * -------------------------------------------------------------------------- */
336 markSignalHandlers (evac_fn evac)
340 p = next_pending_handler;
341 while (p != pending_handler_buf) {
343 evac((StgClosure **)p);
347 #else /* !RTS_USER_SIGNALS */
349 stg_sig_install(StgInt sig STG_UNUSED,
350 StgInt spi STG_UNUSED,
351 StgStablePtr* handler STG_UNUSED,
352 void* mask STG_UNUSED)
354 //barf("User signals not supported");
360 #if defined(RTS_USER_SIGNALS)
361 /* -----------------------------------------------------------------------------
364 * We like to shutdown nicely after receiving a SIGINT, write out the
365 * stats, write profiling info, close open files and flush buffers etc.
366 * -------------------------------------------------------------------------- */
368 pthread_t startup_guy;
372 shutdown_handler(int sig STG_UNUSED)
375 // if I'm a worker thread, send this signal to the guy who
376 // originally called startupHaskell(). Since we're handling
377 // the signal, it won't be a "send to all threads" type of signal
378 // (according to the POSIX threads spec).
379 if (pthread_self() != startup_guy) {
380 pthread_kill(startup_guy, sig);
383 // ToDo: The code for the threaded RTS below does something very
384 // similar. Maybe the SMP special case is not needed
385 // -- Wolfgang Thaller
386 #elif defined(THREADED_RTS)
387 // Make the thread that currently holds the main capability
388 // handle the signal.
389 // This makes sure that awaitEvent() is interrupted
390 if(pthread_self() != signalHandlingThread) {
391 pthread_kill(signalHandlingThread, sig);
396 // If we're already trying to interrupt the RTS, terminate with
397 // extreme prejudice. So the first ^C tries to exit the program
398 // cleanly, and the second one just kills it.
400 stg_exit(EXIT_INTERRUPTED);
406 /* -----------------------------------------------------------------------------
407 * Install default signal handlers.
409 * The RTS installs a default signal handler for catching
410 * SIGINT, so that we can perform an orderly shutdown.
412 * Haskell code may install their own SIGINT handler, which is
413 * fine, provided they're so kind as to put back the old one
414 * when they de-install.
416 * In addition to handling SIGINT, the RTS also handles SIGFPE
417 * by ignoring it. Apparently IEEE requires floating-point
418 * exceptions to be ignored by default, but alpha-dec-osf3
419 * doesn't seem to do so.
420 * -------------------------------------------------------------------------- */
422 initDefaultHandlers()
424 struct sigaction action,oact;
427 startup_guy = pthread_self();
429 #ifdef RTS_SUPPORTS_THREADS
430 handleSignalsInThisThread();
433 // install the SIGINT handler
434 action.sa_handler = shutdown_handler;
435 sigemptyset(&action.sa_mask);
437 if (sigaction(SIGINT, &action, &oact) != 0) {
438 errorBelch("warning: failed to install SIGINT handler");
441 #if defined(HAVE_SIGINTERRUPT)
442 siginterrupt(SIGINT, 1); // isn't this the default? --SDM
445 // install the SIGCONT handler
446 action.sa_handler = cont_handler;
447 sigemptyset(&action.sa_mask);
449 if (sigaction(SIGCONT, &action, &oact) != 0) {
450 errorBelch("warning: failed to install SIGCONT handler");
453 // install the SIGFPE handler
455 // In addition to handling SIGINT, also handle SIGFPE by ignoring it.
456 // Apparently IEEE requires floating-point exceptions to be ignored by
457 // default, but alpha-dec-osf3 doesn't seem to do so.
459 // Commented out by SDM 2/7/2002: this causes an infinite loop on
460 // some architectures when an integer division by zero occurs: we
461 // don't recover from the floating point exception, and the
462 // program just generates another one immediately.
464 action.sa_handler = SIG_IGN;
465 sigemptyset(&action.sa_mask);
467 if (sigaction(SIGFPE, &action, &oact) != 0) {
468 errorBelch("warning: failed to install SIGFPE handler");
472 #ifdef alpha_TARGET_ARCH
473 ieee_set_fp_control(0);
477 #endif /* RTS_USER_SIGNALS */