1 /* -----------------------------------------------------------------------------
2 * $Id: Signals.c,v 1.36 2003/03/29 00:00:41 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>
37 /* SUP: The type of handlers is a little bit, well, doubtful... */
38 static StgInt *handlers = NULL; /* Dynamically grown array of signal handlers */
39 static StgInt nHandlers = 0; /* Size of handlers array */
41 static nat n_haskell_handlers = 0;
43 #define N_PENDING_HANDLERS 16
45 StgPtr pending_handler_buf[N_PENDING_HANDLERS];
46 StgPtr *next_pending_handler = pending_handler_buf;
51 #ifdef RTS_SUPPORTS_THREADS
52 pthread_t signalHandlingThread;
55 // Handle all signals in the current thread.
56 // Called from Capability.c whenever the main capability is granted to a thread
57 // and in installDefaultHandlers
59 handleSignalsInThisThread()
61 #ifdef RTS_SUPPORTS_THREADS
62 signalHandlingThread = pthread_self();
67 /* -----------------------------------------------------------------------------
68 * Allocate/resize the table of signal handlers.
69 * -------------------------------------------------------------------------- */
80 handlers = (StgInt *)stgMallocBytes((sig + 1) * sizeof(StgInt), "more_handlers");
82 handlers = (StgInt *)stgReallocBytes(handlers, (sig + 1) * sizeof(StgInt), "more_handlers");
84 for(i = nHandlers; i <= sig; i++)
85 // Fill in the new slots with default actions
86 handlers[i] = STG_SIG_DFL;
91 /* -----------------------------------------------------------------------------
94 * It seems that shells tend to put stdin back into blocking mode
95 * following a suspend/resume of the process. Here we arrange to put
96 * it back into non-blocking mode. We don't do anything to
97 * stdout/stderr because these handles don't get put into non-blocking
98 * mode at all - see the comments on stdout/stderr in PrelHandle.hsc.
99 * -------------------------------------------------------------------------- */
102 cont_handler(int sig STG_UNUSED)
107 /* -----------------------------------------------------------------------------
108 * Low-level signal handler
110 * Places the requested handler on a stack of pending handlers to be
111 * started up at the next context switch.
112 * -------------------------------------------------------------------------- */
115 generic_handler(int sig)
119 #if defined(THREADED_RTS)
120 // Make the thread that currently holds the main capability
121 // handle the signal.
122 // This makes sure that awaitEvent() is interrupted
123 // and it (hopefully) prevents race conditions
124 // (signal handlers are not atomic with respect to other threads)
126 if(pthread_self() != signalHandlingThread) {
127 pthread_kill(signalHandlingThread, sig);
132 /* Can't call allocate from here. Probably can't call malloc
133 either. However, we have to schedule a new thread somehow.
135 It's probably ok to request a context switch and allow the
136 scheduler to start the handler thread, but how do we
137 communicate this to the scheduler?
139 We need some kind of locking, but with low overhead (i.e. no
140 blocking signals every time around the scheduler).
142 Signal Handlers are atomic (i.e. they can't be interrupted), and
143 we can make use of this. We just need to make sure the
144 critical section of the scheduler can't be interrupted - the
145 only way to do this is to block signals. However, we can lower
146 the overhead by only blocking signals when there are any
147 handlers to run, i.e. the set of pending handlers is
151 /* We use a stack to store the pending signals. We can't
152 dynamically grow this since we can't allocate any memory from
153 within a signal handler.
155 Hence unfortunately we have to bomb out if the buffer
156 overflows. It might be acceptable to carry on in certain
157 circumstances, depending on the signal.
160 *next_pending_handler++ = deRefStablePtr((StgStablePtr)handlers[sig]);
163 if (next_pending_handler == &pending_handler_buf[N_PENDING_HANDLERS]) {
164 prog_belch("too many pending signals");
165 stg_exit(EXIT_FAILURE);
168 // re-establish the signal handler, and carry on
169 sigemptyset(&signals);
170 sigaddset(&signals, sig);
171 sigprocmask(SIG_UNBLOCK, &signals, NULL);
173 // *always* do the SIGCONT handler, even if the user overrides it.
174 if (sig == SIGCONT) {
181 /* -----------------------------------------------------------------------------
182 * Blocking/Unblocking of the user signals
183 * -------------------------------------------------------------------------- */
185 static sigset_t userSignals;
186 static sigset_t savedSignals;
189 initUserSignals(void)
191 sigemptyset(&userSignals);
195 blockUserSignals(void)
197 sigprocmask(SIG_BLOCK, &userSignals, &savedSignals);
201 unblockUserSignals(void)
203 sigprocmask(SIG_SETMASK, &savedSignals, NULL);
207 anyUserHandlers(void)
209 return n_haskell_handlers != 0;
213 awaitUserSignals(void)
215 while (!signals_pending() && !interrupted) {
220 /* -----------------------------------------------------------------------------
221 * Install a Haskell signal handler.
222 * -------------------------------------------------------------------------- */
225 stg_sig_install(int sig, int spi, StgStablePtr *handler, void *mask)
227 sigset_t signals, osignals;
228 struct sigaction action;
231 // Block the signal until we figure out what to do
232 // Count on this to fail if the signal number is invalid
233 if (sig < 0 || sigemptyset(&signals) ||
234 sigaddset(&signals, sig) || sigprocmask(SIG_BLOCK, &signals, &osignals)) {
240 previous_spi = handlers[sig];
246 handlers[sig] = STG_SIG_IGN;
247 sigdelset(&userSignals, sig);
248 action.sa_handler = SIG_IGN;
252 handlers[sig] = STG_SIG_DFL;
253 sigdelset(&userSignals, sig);
254 action.sa_handler = SIG_DFL;
259 handlers[sig] = (StgInt)*handler;
260 sigaddset(&userSignals, sig);
261 action.sa_handler = generic_handler;
262 if (spi == STG_SIG_RST) {
263 action.sa_flags = SA_RESETHAND;
265 n_haskell_handlers++;
269 barf("stg_sig_install: bad spi");
273 action.sa_mask = *(sigset_t *)mask;
275 sigemptyset(&action.sa_mask);
277 action.sa_flags |= sig == SIGCHLD && nocldstop ? SA_NOCLDSTOP : 0;
279 if (sigaction(sig, &action, NULL) ||
280 sigprocmask(SIG_SETMASK, &osignals, NULL))
282 // need to return an error code, so avoid a stable pointer leak
283 // by freeing the previous handler if there was one.
284 if (previous_spi >= 0) {
285 freeStablePtr(stgCast(StgStablePtr,handlers[sig]));
286 n_haskell_handlers--;
291 if (previous_spi == STG_SIG_DFL || previous_spi == STG_SIG_IGN
292 || previous_spi == STG_SIG_ERR) {
295 *handler = (StgStablePtr)previous_spi;
300 /* -----------------------------------------------------------------------------
301 * Creating new threads for the pending signal handlers.
302 * -------------------------------------------------------------------------- */
304 startSignalHandlers(void)
308 while (next_pending_handler != pending_handler_buf) {
310 next_pending_handler--;
313 createIOThread(RtsFlags.GcFlags.initialStkSize,
314 (StgClosure *) *next_pending_handler));
317 unblockUserSignals();
320 /* ----------------------------------------------------------------------------
321 * Mark signal handlers during GC.
323 * We do this rather than trying to start all the signal handlers
324 * prior to GC, because that requires extra heap for the new threads.
325 * Signals must be blocked (see blockUserSignals() above) during GC to
326 * avoid race conditions.
327 * -------------------------------------------------------------------------- */
330 markSignalHandlers (evac_fn evac)
334 p = next_pending_handler;
335 while (p != pending_handler_buf) {
337 evac((StgClosure **)p);
343 stg_sig_install(StgInt sig, StgInt spi, StgStablePtr handler, sigset_t *mask)
345 // don't fflush(stdout); WORKAROUND bug in Linux glibc
346 barf("no signal handling support in a parallel implementation");
350 startSignalHandlers(void)
355 /* -----------------------------------------------------------------------------
358 * We like to shutdown nicely after receiving a SIGINT, write out the
359 * stats, write profiling info, close open files and flush buffers etc.
360 * -------------------------------------------------------------------------- */
362 pthread_t startup_guy;
366 shutdown_handler(int sig STG_UNUSED)
369 // if I'm a worker thread, send this signal to the guy who
370 // originally called startupHaskell(). Since we're handling
371 // the signal, it won't be a "send to all threads" type of signal
372 // (according to the POSIX threads spec).
373 if (pthread_self() != startup_guy) {
374 pthread_kill(startup_guy, sig);
377 // ToDo: The code for the threaded RTS below does something very
378 // similar. Maybe the SMP special case is not needed
379 // -- Wolfgang Thaller
380 #elif defined(THREADED_RTS)
381 // Make the thread that currently holds the main capability
382 // handle the signal.
383 // This makes sure that awaitEvent() is interrupted
384 if(pthread_self() != signalHandlingThread) {
385 pthread_kill(signalHandlingThread, sig);
390 // If we're already trying to interrupt the RTS, terminate with
391 // extreme prejudice. So the first ^C tries to exit the program
392 // cleanly, and the second one just kills it.
394 stg_exit(EXIT_INTERRUPTED);
400 /* -----------------------------------------------------------------------------
401 * Install default signal handlers.
403 * The RTS installs a default signal handler for catching
404 * SIGINT, so that we can perform an orderly shutdown.
406 * Haskell code may install their own SIGINT handler, which is
407 * fine, provided they're so kind as to put back the old one
408 * when they de-install.
410 * In addition to handling SIGINT, the RTS also handles SIGFPE
411 * by ignoring it. Apparently IEEE requires floating-point
412 * exceptions to be ignored by default, but alpha-dec-osf3
413 * doesn't seem to do so.
414 * -------------------------------------------------------------------------- */
416 initDefaultHandlers()
418 struct sigaction action,oact;
421 startup_guy = pthread_self();
423 #ifdef RTS_SUPPORTS_THREADS
424 handleSignalsInThisThread();
427 // install the SIGINT handler
428 action.sa_handler = shutdown_handler;
429 sigemptyset(&action.sa_mask);
431 if (sigaction(SIGINT, &action, &oact) != 0) {
432 prog_belch("warning: failed to install SIGINT handler");
435 #ifndef cygwin32_TARGET_OS
436 siginterrupt(SIGINT, 1); // isn't this the default? --SDM
439 // install the SIGCONT handler
440 action.sa_handler = cont_handler;
441 sigemptyset(&action.sa_mask);
443 if (sigaction(SIGCONT, &action, &oact) != 0) {
444 prog_belch("warning: failed to install SIGCONT handler");
447 // install the SIGFPE handler
449 // In addition to handling SIGINT, also handle SIGFPE by ignoring it.
450 // Apparently IEEE requires floating-point exceptions to be ignored by
451 // default, but alpha-dec-osf3 doesn't seem to do so.
453 // Commented out by SDM 2/7/2002: this causes an infinite loop on
454 // some architectures when an integer division by zero occurs: we
455 // don't recover from the floating point exception, and the
456 // program just generates another one immediately.
458 action.sa_handler = SIG_IGN;
459 sigemptyset(&action.sa_mask);
461 if (sigaction(SIGFPE, &action, &oact) != 0) {
462 prog_belch("warning: failed to install SIGFPE handler");
466 #ifdef alpha_TARGET_ARCH
467 ieee_set_fp_control(0);