1 /* -----------------------------------------------------------------------------
3 * (c) The GHC Team, 1998-2005
5 * Signal processing / handling.
7 * ---------------------------------------------------------------------------*/
9 /* This is non-Posix-compliant.
10 #include "PosixSource.h"
15 #include "RtsSignals.h"
16 #include "posix/Signals.h"
20 #ifdef alpha_HOST_ARCH
21 # if defined(linux_HOST_OS)
24 # include <machine/fpu.h>
38 /* This curious flag is provided for the benefit of the Haskell binding
39 * to POSIX.1 to control whether or not to include SA_NOCLDSTOP when
40 * installing a SIGCHLD handler.
44 /* -----------------------------------------------------------------------------
45 * The table of signal handlers
46 * -------------------------------------------------------------------------- */
48 #if defined(RTS_USER_SIGNALS)
50 /* SUP: The type of handlers is a little bit, well, doubtful... */
51 StgInt *signal_handlers = NULL; /* Dynamically grown array of signal handlers */
52 static StgInt nHandlers = 0; /* Size of handlers array */
54 static nat n_haskell_handlers = 0;
56 /* -----------------------------------------------------------------------------
57 * Allocate/resize the table of signal handlers.
58 * -------------------------------------------------------------------------- */
68 if (signal_handlers == NULL)
69 signal_handlers = (StgInt *)stgMallocBytes((sig + 1) * sizeof(StgInt), "more_handlers");
71 signal_handlers = (StgInt *)stgReallocBytes(signal_handlers, (sig + 1) * sizeof(StgInt), "more_handlers");
73 for(i = nHandlers; i <= sig; i++)
74 // Fill in the new slots with default actions
75 signal_handlers[i] = STG_SIG_DFL;
80 /* -----------------------------------------------------------------------------
83 * The mechanism for starting handlers differs between the threaded
84 * (THREADED_RTS) and non-threaded versions of the RTS.
86 * When the RTS is single-threaded, we just write the pending signal
87 * handlers into a buffer, and start a thread for each one in the
90 * When THREADED_RTS, the problem is that signals might be
91 * delivered to multiple threads, so we would need to synchronise
92 * access to pending_handler_buf somehow. Using thread
93 * synchronisation from a signal handler isn't possible in general
94 * (some OSs support it, eg. MacOS X, but not all). So instead:
96 * - the signal handler writes the signal number into the pipe
97 * managed by the IO manager thread (see GHC.Conc).
98 * - the IO manager picks up the signal number and calls
99 * startSignalHandler() to start the thread.
101 * This also has the nice property that we don't need to arrange to
102 * wake up a worker task to start the signal handler: the IO manager
103 * wakes up when we write into the pipe.
105 * -------------------------------------------------------------------------- */
107 // Here's the pipe into which we will send our signals
108 static int io_manager_pipe = -1;
111 setIOManagerPipe (int fd)
113 // only called when THREADED_RTS, but unconditionally
114 // compiled here because GHC.Conc depends on it.
115 io_manager_pipe = fd;
118 #if !defined(THREADED_RTS)
120 #define N_PENDING_HANDLERS 16
122 StgPtr pending_handler_buf[N_PENDING_HANDLERS];
123 StgPtr *next_pending_handler = pending_handler_buf;
125 #endif /* THREADED_RTS */
127 /* -----------------------------------------------------------------------------
130 * It seems that shells tend to put stdin back into blocking mode
131 * following a suspend/resume of the process. Here we arrange to put
132 * it back into non-blocking mode. We don't do anything to
133 * stdout/stderr because these handles don't get put into non-blocking
134 * mode at all - see the comments on stdout/stderr in PrelHandle.hsc.
135 * -------------------------------------------------------------------------- */
138 cont_handler(int sig STG_UNUSED)
143 /* -----------------------------------------------------------------------------
144 * Low-level signal handler
146 * Places the requested handler on a stack of pending handlers to be
147 * started up at the next context switch.
148 * -------------------------------------------------------------------------- */
151 generic_handler(int sig)
155 #if defined(THREADED_RTS)
157 if (io_manager_pipe != -1)
159 // Write the signal number into the pipe as a single byte. We
160 // hope that signals fit into a byte...
161 StgWord8 csig = (StgWord8)sig;
162 write(io_manager_pipe, &csig, 1);
164 // If the IO manager hasn't told us what the FD of the write end
165 // of its pipe is, there's not much we can do here, so just ignore
168 #else /* not THREADED_RTS */
170 /* Can't call allocate from here. Probably can't call malloc
171 either. However, we have to schedule a new thread somehow.
173 It's probably ok to request a context switch and allow the
174 scheduler to start the handler thread, but how do we
175 communicate this to the scheduler?
177 We need some kind of locking, but with low overhead (i.e. no
178 blocking signals every time around the scheduler).
180 Signal Handlers are atomic (i.e. they can't be interrupted), and
181 we can make use of this. We just need to make sure the
182 critical section of the scheduler can't be interrupted - the
183 only way to do this is to block signals. However, we can lower
184 the overhead by only blocking signals when there are any
185 handlers to run, i.e. the set of pending handlers is
189 /* We use a stack to store the pending signals. We can't
190 dynamically grow this since we can't allocate any memory from
191 within a signal handler.
193 Hence unfortunately we have to bomb out if the buffer
194 overflows. It might be acceptable to carry on in certain
195 circumstances, depending on the signal.
198 *next_pending_handler++ = deRefStablePtr((StgStablePtr)signal_handlers[sig]);
201 if (next_pending_handler == &pending_handler_buf[N_PENDING_HANDLERS]) {
202 errorBelch("too many pending signals");
203 stg_exit(EXIT_FAILURE);
206 #endif /* THREADED_RTS */
208 // re-establish the signal handler, and carry on
209 sigemptyset(&signals);
210 sigaddset(&signals, sig);
211 sigprocmask(SIG_UNBLOCK, &signals, NULL);
213 // *always* do the SIGCONT handler, even if the user overrides it.
214 if (sig == SIGCONT) {
221 /* -----------------------------------------------------------------------------
222 * Blocking/Unblocking of the user signals
223 * -------------------------------------------------------------------------- */
225 static sigset_t userSignals;
226 static sigset_t savedSignals;
229 initUserSignals(void)
231 sigemptyset(&userSignals);
235 blockUserSignals(void)
237 sigprocmask(SIG_BLOCK, &userSignals, &savedSignals);
241 unblockUserSignals(void)
243 sigprocmask(SIG_SETMASK, &savedSignals, NULL);
247 anyUserHandlers(void)
249 return n_haskell_handlers != 0;
252 #if !defined(THREADED_RTS)
254 awaitUserSignals(void)
256 while (!signals_pending() && sched_state == SCHED_RUNNING) {
262 /* -----------------------------------------------------------------------------
263 * Install a Haskell signal handler.
264 * -------------------------------------------------------------------------- */
267 stg_sig_install(int sig, int spi, StgStablePtr *handler, void *mask)
269 sigset_t signals, osignals;
270 struct sigaction action;
273 // Block the signal until we figure out what to do
274 // Count on this to fail if the signal number is invalid
275 if (sig < 0 || sigemptyset(&signals) ||
276 sigaddset(&signals, sig) || sigprocmask(SIG_BLOCK, &signals, &osignals)) {
282 previous_spi = signal_handlers[sig];
288 signal_handlers[sig] = STG_SIG_IGN;
289 sigdelset(&userSignals, sig);
290 action.sa_handler = SIG_IGN;
294 signal_handlers[sig] = STG_SIG_DFL;
295 sigdelset(&userSignals, sig);
296 action.sa_handler = SIG_DFL;
301 signal_handlers[sig] = (StgInt)*handler;
302 sigaddset(&userSignals, sig);
303 action.sa_handler = generic_handler;
304 if (spi == STG_SIG_RST) {
305 action.sa_flags = SA_RESETHAND;
307 n_haskell_handlers++;
311 barf("stg_sig_install: bad spi");
315 action.sa_mask = *(sigset_t *)mask;
317 sigemptyset(&action.sa_mask);
319 action.sa_flags |= sig == SIGCHLD && nocldstop ? SA_NOCLDSTOP : 0;
321 if (sigaction(sig, &action, NULL) ||
322 sigprocmask(SIG_SETMASK, &osignals, NULL))
324 // need to return an error code, so avoid a stable pointer leak
325 // by freeing the previous handler if there was one.
326 if (previous_spi >= 0) {
327 freeStablePtr(stgCast(StgStablePtr,signal_handlers[sig]));
328 n_haskell_handlers--;
333 if (previous_spi == STG_SIG_DFL || previous_spi == STG_SIG_IGN
334 || previous_spi == STG_SIG_ERR) {
337 *handler = (StgStablePtr)previous_spi;
342 /* -----------------------------------------------------------------------------
343 * Creating new threads for signal handlers.
344 * -------------------------------------------------------------------------- */
346 #if !defined(THREADED_RTS)
348 startSignalHandlers(Capability *cap)
352 while (next_pending_handler != pending_handler_buf) {
354 next_pending_handler--;
358 RtsFlags.GcFlags.initialStkSize,
359 (StgClosure *) *next_pending_handler));
362 unblockUserSignals();
366 /* ----------------------------------------------------------------------------
367 * Mark signal handlers during GC.
369 * We do this rather than trying to start all the signal handlers
370 * prior to GC, because that requires extra heap for the new threads.
371 * Signals must be blocked (see blockUserSignals() above) during GC to
372 * avoid race conditions.
373 * -------------------------------------------------------------------------- */
375 #if !defined(THREADED_RTS)
377 markSignalHandlers (evac_fn evac)
381 p = next_pending_handler;
382 while (p != pending_handler_buf) {
384 evac((StgClosure **)p);
389 markSignalHandlers (evac_fn evac STG_UNUSED)
394 #else /* !RTS_USER_SIGNALS */
396 stg_sig_install(StgInt sig STG_UNUSED,
397 StgInt spi STG_UNUSED,
398 StgStablePtr* handler STG_UNUSED,
399 void* mask STG_UNUSED)
401 //barf("User signals not supported");
407 #if defined(RTS_USER_SIGNALS)
408 /* -----------------------------------------------------------------------------
411 * We like to shutdown nicely after receiving a SIGINT, write out the
412 * stats, write profiling info, close open files and flush buffers etc.
413 * -------------------------------------------------------------------------- */
415 pthread_t startup_guy;
419 shutdown_handler(int sig STG_UNUSED)
422 // if I'm a worker thread, send this signal to the guy who
423 // originally called startupHaskell(). Since we're handling
424 // the signal, it won't be a "send to all threads" type of signal
425 // (according to the POSIX threads spec).
426 if (pthread_self() != startup_guy) {
427 pthread_kill(startup_guy, sig);
432 // If we're already trying to interrupt the RTS, terminate with
433 // extreme prejudice. So the first ^C tries to exit the program
434 // cleanly, and the second one just kills it.
435 if (sched_state >= SCHED_INTERRUPTING) {
436 stg_exit(EXIT_INTERRUPTED);
442 /* -----------------------------------------------------------------------------
443 * Install default signal handlers.
445 * The RTS installs a default signal handler for catching
446 * SIGINT, so that we can perform an orderly shutdown.
448 * Haskell code may install their own SIGINT handler, which is
449 * fine, provided they're so kind as to put back the old one
450 * when they de-install.
452 * In addition to handling SIGINT, the RTS also handles SIGFPE
453 * by ignoring it. Apparently IEEE requires floating-point
454 * exceptions to be ignored by default, but alpha-dec-osf3
455 * doesn't seem to do so.
456 * -------------------------------------------------------------------------- */
458 initDefaultHandlers()
460 struct sigaction action,oact;
463 startup_guy = pthread_self();
466 // install the SIGINT handler
467 action.sa_handler = shutdown_handler;
468 sigemptyset(&action.sa_mask);
470 if (sigaction(SIGINT, &action, &oact) != 0) {
471 errorBelch("warning: failed to install SIGINT handler");
474 #if defined(HAVE_SIGINTERRUPT)
475 siginterrupt(SIGINT, 1); // isn't this the default? --SDM
478 // install the SIGCONT handler
479 action.sa_handler = cont_handler;
480 sigemptyset(&action.sa_mask);
482 if (sigaction(SIGCONT, &action, &oact) != 0) {
483 errorBelch("warning: failed to install SIGCONT handler");
486 // install the SIGFPE handler
488 // In addition to handling SIGINT, also handle SIGFPE by ignoring it.
489 // Apparently IEEE requires floating-point exceptions to be ignored by
490 // default, but alpha-dec-osf3 doesn't seem to do so.
492 // Commented out by SDM 2/7/2002: this causes an infinite loop on
493 // some architectures when an integer division by zero occurs: we
494 // don't recover from the floating point exception, and the
495 // program just generates another one immediately.
497 action.sa_handler = SIG_IGN;
498 sigemptyset(&action.sa_mask);
500 if (sigaction(SIGFPE, &action, &oact) != 0) {
501 errorBelch("warning: failed to install SIGFPE handler");
505 #ifdef alpha_HOST_ARCH
506 ieee_set_fp_control(0);
510 #endif /* RTS_USER_SIGNALS */