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 #include "ThrIOManager.h"
22 #ifdef alpha_HOST_ARCH
23 # if defined(linux_HOST_OS)
26 # include <machine/fpu.h>
45 /* This curious flag is provided for the benefit of the Haskell binding
46 * to POSIX.1 to control whether or not to include SA_NOCLDSTOP when
47 * installing a SIGCHLD handler.
51 /* -----------------------------------------------------------------------------
52 * The table of signal handlers
53 * -------------------------------------------------------------------------- */
55 #if defined(RTS_USER_SIGNALS)
57 /* SUP: The type of handlers is a little bit, well, doubtful... */
58 StgInt *signal_handlers = NULL; /* Dynamically grown array of signal handlers */
59 static StgInt nHandlers = 0; /* Size of handlers array */
61 static nat n_haskell_handlers = 0;
63 /* -----------------------------------------------------------------------------
64 * Allocate/resize the table of signal handlers.
65 * -------------------------------------------------------------------------- */
68 more_handlers(int sig)
75 if (signal_handlers == NULL)
76 signal_handlers = (StgInt *)stgMallocBytes((sig + 1) * sizeof(StgInt), "more_handlers");
78 signal_handlers = (StgInt *)stgReallocBytes(signal_handlers, (sig + 1) * sizeof(StgInt), "more_handlers");
80 for(i = nHandlers; i <= sig; i++)
81 // Fill in the new slots with default actions
82 signal_handlers[i] = STG_SIG_DFL;
87 // Here's the pipe into which we will send our signals
88 static int io_manager_pipe = -1;
90 #define IO_MANAGER_WAKEUP 0xff
91 #define IO_MANAGER_DIE 0xfe
94 setIOManagerPipe (int fd)
96 // only called when THREADED_RTS, but unconditionally
97 // compiled here because GHC.Conc depends on it.
98 if (io_manager_pipe < 0) {
103 #if defined(THREADED_RTS)
105 ioManagerWakeup (void)
108 // Wake up the IO Manager thread by sending a byte down its pipe
109 if (io_manager_pipe >= 0) {
110 StgWord8 byte = (StgWord8)IO_MANAGER_WAKEUP;
111 r = write(io_manager_pipe, &byte, 1);
112 if (r == -1) { sysErrorBelch("ioManagerWakeup: write"); }
120 // Ask the IO Manager thread to exit
121 if (io_manager_pipe >= 0) {
122 StgWord8 byte = (StgWord8)IO_MANAGER_DIE;
123 r = write(io_manager_pipe, &byte, 1);
124 if (r == -1) { sysErrorBelch("ioManagerDie: write"); }
125 close(io_manager_pipe);
126 io_manager_pipe = -1;
131 ioManagerStart (void)
133 // Make sure the IO manager thread is running
135 if (io_manager_pipe < 0) {
137 cap = rts_evalIO(cap,&base_GHCziConc_ensureIOManagerIsRunning_closure,NULL);
143 #if !defined(THREADED_RTS)
145 #define N_PENDING_HANDLERS 16
147 siginfo_t pending_handler_buf[N_PENDING_HANDLERS];
148 siginfo_t *next_pending_handler = pending_handler_buf;
150 #endif /* THREADED_RTS */
152 /* -----------------------------------------------------------------------------
153 * Low-level signal handler
155 * Places the requested handler on a stack of pending handlers to be
156 * started up at the next context switch.
157 * -------------------------------------------------------------------------- */
160 generic_handler(int sig USED_IF_THREADS,
164 #if defined(THREADED_RTS)
166 if (io_manager_pipe != -1)
168 StgWord8 buf[sizeof(siginfo_t) + 1];
172 memcpy(buf+1, info, sizeof(siginfo_t));
173 r = write(io_manager_pipe, buf, sizeof(siginfo_t)+1);
174 if (r == -1 && errno == EAGAIN)
176 errorBelch("lost signal due to full pipe: %d\n", sig);
179 // If the IO manager hasn't told us what the FD of the write end
180 // of its pipe is, there's not much we can do here, so just ignore
183 #else /* not THREADED_RTS */
185 /* Can't call allocate from here. Probably can't call malloc
186 either. However, we have to schedule a new thread somehow.
188 It's probably ok to request a context switch and allow the
189 scheduler to start the handler thread, but how do we
190 communicate this to the scheduler?
192 We need some kind of locking, but with low overhead (i.e. no
193 blocking signals every time around the scheduler).
195 Signal Handlers are atomic (i.e. they can't be interrupted), and
196 we can make use of this. We just need to make sure the
197 critical section of the scheduler can't be interrupted - the
198 only way to do this is to block signals. However, we can lower
199 the overhead by only blocking signals when there are any
200 handlers to run, i.e. the set of pending handlers is
204 /* We use a stack to store the pending signals. We can't
205 dynamically grow this since we can't allocate any memory from
206 within a signal handler.
208 Hence unfortunately we have to bomb out if the buffer
209 overflows. It might be acceptable to carry on in certain
210 circumstances, depending on the signal.
213 memcpy(next_pending_handler, info, sizeof(siginfo_t));
215 next_pending_handler++;
218 if (next_pending_handler == &pending_handler_buf[N_PENDING_HANDLERS]) {
219 errorBelch("too many pending signals");
220 stg_exit(EXIT_FAILURE);
223 contextSwitchCapability(&MainCapability);
225 #endif /* THREADED_RTS */
228 /* -----------------------------------------------------------------------------
229 * Blocking/Unblocking of the user signals
230 * -------------------------------------------------------------------------- */
232 static sigset_t userSignals;
233 static sigset_t savedSignals;
236 initUserSignals(void)
238 sigemptyset(&userSignals);
240 getStablePtr((StgPtr)&base_GHCziConc_runHandlers_closure);
241 // needed to keep runHandler alive
246 blockUserSignals(void)
248 sigprocmask(SIG_BLOCK, &userSignals, &savedSignals);
252 unblockUserSignals(void)
254 sigprocmask(SIG_SETMASK, &savedSignals, NULL);
258 anyUserHandlers(void)
260 return n_haskell_handlers != 0;
263 #if !defined(THREADED_RTS)
265 awaitUserSignals(void)
267 while (!signals_pending() && sched_state == SCHED_RUNNING) {
273 /* -----------------------------------------------------------------------------
274 * Install a Haskell signal handler.
276 * We should really do this in Haskell in GHC.Conc, and share the
277 * signal_handlers array with the one there.
279 * -------------------------------------------------------------------------- */
282 stg_sig_install(int sig, int spi, void *mask)
284 sigset_t signals, osignals;
285 struct sigaction action;
288 // Block the signal until we figure out what to do
289 // Count on this to fail if the signal number is invalid
290 if (sig < 0 || sigemptyset(&signals) ||
291 sigaddset(&signals, sig) || sigprocmask(SIG_BLOCK, &signals, &osignals)) {
297 previous_spi = signal_handlers[sig];
303 action.sa_handler = SIG_IGN;
307 action.sa_handler = SIG_DFL;
311 action.sa_flags |= SA_RESETHAND;
314 action.sa_sigaction = generic_handler;
315 action.sa_flags |= SA_SIGINFO;
319 barf("stg_sig_install: bad spi");
323 action.sa_mask = *(sigset_t *)mask;
325 sigemptyset(&action.sa_mask);
327 action.sa_flags |= sig == SIGCHLD && nocldstop ? SA_NOCLDSTOP : 0;
329 if (sigaction(sig, &action, NULL))
331 errorBelch("sigaction");
335 signal_handlers[sig] = spi;
340 sigaddset(&userSignals, sig);
341 if (previous_spi != STG_SIG_HAN && previous_spi != STG_SIG_RST) {
342 n_haskell_handlers++;
347 sigdelset(&userSignals, sig);
348 if (previous_spi == STG_SIG_HAN || previous_spi == STG_SIG_RST) {
349 n_haskell_handlers--;
354 if (sigprocmask(SIG_SETMASK, &osignals, NULL))
356 errorBelch("sigprocmask");
363 /* -----------------------------------------------------------------------------
364 * Creating new threads for signal handlers.
365 * -------------------------------------------------------------------------- */
367 #if !defined(THREADED_RTS)
369 startSignalHandlers(Capability *cap)
376 while (next_pending_handler != pending_handler_buf) {
378 next_pending_handler--;
380 sig = next_pending_handler->si_signo;
381 if (signal_handlers[sig] == STG_SIG_DFL) {
382 continue; // handler has been changed.
385 info = stgMallocBytes(sizeof(siginfo_t), "startSignalHandlers");
386 // freed by runHandler
387 memcpy(info, next_pending_handler, sizeof(siginfo_t));
391 RtsFlags.GcFlags.initialStkSize,
394 &base_GHCziConc_runHandlers_closure,
395 rts_mkPtr(cap, info)),
396 rts_mkInt(cap, info->si_signo))));
399 unblockUserSignals();
403 /* ----------------------------------------------------------------------------
404 * Mark signal handlers during GC.
405 * -------------------------------------------------------------------------- */
408 markSignalHandlers (evac_fn evac STG_UNUSED, void *user STG_UNUSED)
413 #else /* !RTS_USER_SIGNALS */
415 stg_sig_install(StgInt sig STG_UNUSED,
416 StgInt spi STG_UNUSED,
417 void* mask STG_UNUSED)
419 //barf("User signals not supported");
425 #if defined(RTS_USER_SIGNALS)
426 /* -----------------------------------------------------------------------------
429 * We like to shutdown nicely after receiving a SIGINT, write out the
430 * stats, write profiling info, close open files and flush buffers etc.
431 * -------------------------------------------------------------------------- */
433 shutdown_handler(int sig STG_UNUSED)
435 // If we're already trying to interrupt the RTS, terminate with
436 // extreme prejudice. So the first ^C tries to exit the program
437 // cleanly, and the second one just kills it.
438 if (sched_state >= SCHED_INTERRUPTING) {
439 stg_exit(EXIT_INTERRUPTED);
445 /* -----------------------------------------------------------------------------
446 * Install default signal handlers.
448 * The RTS installs a default signal handler for catching
449 * SIGINT, so that we can perform an orderly shutdown.
451 * Haskell code may install their own SIGINT handler, which is
452 * fine, provided they're so kind as to put back the old one
453 * when they de-install.
455 * In addition to handling SIGINT, the RTS also handles SIGFPE
456 * by ignoring it. Apparently IEEE requires floating-point
457 * exceptions to be ignored by default, but alpha-dec-osf3
458 * doesn't seem to do so.
459 * -------------------------------------------------------------------------- */
461 initDefaultHandlers(void)
463 struct sigaction action,oact;
465 // install the SIGINT handler
466 action.sa_handler = shutdown_handler;
467 sigemptyset(&action.sa_mask);
469 if (sigaction(SIGINT, &action, &oact) != 0) {
470 sysErrorBelch("warning: failed to install SIGINT handler");
473 #if defined(HAVE_SIGINTERRUPT)
474 siginterrupt(SIGINT, 1); // isn't this the default? --SDM
477 // install the SIGFPE handler
479 // In addition to handling SIGINT, also handle SIGFPE by ignoring it.
480 // Apparently IEEE requires floating-point exceptions to be ignored by
481 // default, but alpha-dec-osf3 doesn't seem to do so.
483 // Commented out by SDM 2/7/2002: this causes an infinite loop on
484 // some architectures when an integer division by zero occurs: we
485 // don't recover from the floating point exception, and the
486 // program just generates another one immediately.
488 action.sa_handler = SIG_IGN;
489 sigemptyset(&action.sa_mask);
491 if (sigaction(SIGFPE, &action, &oact) != 0) {
492 sysErrorBelch("warning: failed to install SIGFPE handler");
496 #ifdef alpha_HOST_ARCH
497 ieee_set_fp_control(0);
500 // ignore SIGPIPE; see #1619
501 action.sa_handler = SIG_IGN;
502 sigemptyset(&action.sa_mask);
504 if (sigaction(SIGPIPE, &action, &oact) != 0) {
505 sysErrorBelch("warning: failed to install SIGPIPE handler");
510 resetDefaultHandlers(void)
512 struct sigaction action;
514 action.sa_handler = SIG_DFL;
515 sigemptyset(&action.sa_mask);
519 if (sigaction(SIGINT, &action, NULL) != 0) {
520 sysErrorBelch("warning: failed to uninstall SIGINT handler");
523 if (sigaction(SIGPIPE, &action, NULL) != 0) {
524 sysErrorBelch("warning: failed to uninstall SIGPIPE handler");
529 freeSignalHandlers(void) {
530 if (signal_handlers != NULL) {
531 stgFree(signal_handlers);
535 #endif /* RTS_USER_SIGNALS */