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.
101 #if defined(THREADED_RTS)
103 ioManagerWakeup (void)
105 // Wake up the IO Manager thread by sending a byte down its pipe
106 if (io_manager_pipe >= 0) {
107 StgWord8 byte = (StgWord8)IO_MANAGER_WAKEUP;
108 write(io_manager_pipe, &byte, 1);
115 // Ask the IO Manager thread to exit
116 if (io_manager_pipe >= 0) {
117 StgWord8 byte = (StgWord8)IO_MANAGER_DIE;
118 write(io_manager_pipe, &byte, 1);
119 close(io_manager_pipe);
120 io_manager_pipe = -1;
125 ioManagerStart (void)
127 // Make sure the IO manager thread is running
129 if (io_manager_pipe < 0) {
131 cap = rts_evalIO(cap,&base_GHCziConc_ensureIOManagerIsRunning_closure,NULL);
137 #if !defined(THREADED_RTS)
139 #define N_PENDING_HANDLERS 16
141 siginfo_t pending_handler_buf[N_PENDING_HANDLERS];
142 siginfo_t *next_pending_handler = pending_handler_buf;
144 #endif /* THREADED_RTS */
146 /* -----------------------------------------------------------------------------
147 * Low-level signal handler
149 * Places the requested handler on a stack of pending handlers to be
150 * started up at the next context switch.
151 * -------------------------------------------------------------------------- */
154 generic_handler(int sig USED_IF_THREADS,
160 #if defined(THREADED_RTS)
162 if (io_manager_pipe != -1)
164 StgWord8 buf[sizeof(siginfo_t) + 1];
168 memcpy(buf+1, info, sizeof(siginfo_t));
169 r = write(io_manager_pipe, buf, sizeof(siginfo_t)+1);
170 if (r == -1 && errno == EAGAIN)
172 errorBelch("lost signal due to full pipe: %d\n", sig);
175 // If the IO manager hasn't told us what the FD of the write end
176 // of its pipe is, there's not much we can do here, so just ignore
179 #else /* not THREADED_RTS */
181 /* Can't call allocate from here. Probably can't call malloc
182 either. However, we have to schedule a new thread somehow.
184 It's probably ok to request a context switch and allow the
185 scheduler to start the handler thread, but how do we
186 communicate this to the scheduler?
188 We need some kind of locking, but with low overhead (i.e. no
189 blocking signals every time around the scheduler).
191 Signal Handlers are atomic (i.e. they can't be interrupted), and
192 we can make use of this. We just need to make sure the
193 critical section of the scheduler can't be interrupted - the
194 only way to do this is to block signals. However, we can lower
195 the overhead by only blocking signals when there are any
196 handlers to run, i.e. the set of pending handlers is
200 /* We use a stack to store the pending signals. We can't
201 dynamically grow this since we can't allocate any memory from
202 within a signal handler.
204 Hence unfortunately we have to bomb out if the buffer
205 overflows. It might be acceptable to carry on in certain
206 circumstances, depending on the signal.
209 memcpy(next_pending_handler, info, sizeof(siginfo_t));
211 next_pending_handler++;
214 if (next_pending_handler == &pending_handler_buf[N_PENDING_HANDLERS]) {
215 errorBelch("too many pending signals");
216 stg_exit(EXIT_FAILURE);
219 MainCapability.context_switch = 1;
221 #endif /* THREADED_RTS */
223 // re-establish the signal handler, and carry on
224 sigemptyset(&signals);
225 sigaddset(&signals, sig);
226 sigprocmask(SIG_UNBLOCK, &signals, NULL);
229 /* -----------------------------------------------------------------------------
230 * Blocking/Unblocking of the user signals
231 * -------------------------------------------------------------------------- */
233 static sigset_t userSignals;
234 static sigset_t savedSignals;
237 initUserSignals(void)
239 sigemptyset(&userSignals);
241 getStablePtr((StgPtr)&base_GHCziConc_runHandlers_closure);
242 // needed to keep runHandler alive
247 blockUserSignals(void)
249 sigprocmask(SIG_BLOCK, &userSignals, &savedSignals);
253 unblockUserSignals(void)
255 sigprocmask(SIG_SETMASK, &savedSignals, NULL);
259 anyUserHandlers(void)
261 return n_haskell_handlers != 0;
264 #if !defined(THREADED_RTS)
266 awaitUserSignals(void)
268 while (!signals_pending() && sched_state == SCHED_RUNNING) {
274 /* -----------------------------------------------------------------------------
275 * Install a Haskell signal handler.
277 * We should really do this in Haskell in GHC.Conc, and share the
278 * signal_handlers array with the one there.
280 * -------------------------------------------------------------------------- */
283 stg_sig_install(int sig, int spi, void *mask)
285 sigset_t signals, osignals;
286 struct sigaction action;
289 // Block the signal until we figure out what to do
290 // Count on this to fail if the signal number is invalid
291 if (sig < 0 || sigemptyset(&signals) ||
292 sigaddset(&signals, sig) || sigprocmask(SIG_BLOCK, &signals, &osignals)) {
298 previous_spi = signal_handlers[sig];
304 action.sa_handler = SIG_IGN;
308 action.sa_handler = SIG_DFL;
312 action.sa_flags |= SA_RESETHAND;
315 action.sa_sigaction = generic_handler;
316 action.sa_flags |= SA_SIGINFO;
320 barf("stg_sig_install: bad spi");
324 action.sa_mask = *(sigset_t *)mask;
326 sigemptyset(&action.sa_mask);
328 action.sa_flags |= sig == SIGCHLD && nocldstop ? SA_NOCLDSTOP : 0;
330 if (sigaction(sig, &action, NULL))
332 errorBelch("sigaction");
336 signal_handlers[sig] = spi;
341 sigaddset(&userSignals, sig);
342 if (previous_spi != STG_SIG_HAN && previous_spi != STG_SIG_RST) {
343 n_haskell_handlers++;
348 sigdelset(&userSignals, sig);
349 if (previous_spi == STG_SIG_HAN || previous_spi == STG_SIG_RST) {
350 n_haskell_handlers--;
355 if (sigprocmask(SIG_SETMASK, &osignals, NULL))
357 errorBelch("sigprocmask");
364 /* -----------------------------------------------------------------------------
365 * Creating new threads for signal handlers.
366 * -------------------------------------------------------------------------- */
368 #if !defined(THREADED_RTS)
370 startSignalHandlers(Capability *cap)
377 while (next_pending_handler != pending_handler_buf) {
379 next_pending_handler--;
381 sig = next_pending_handler->si_signo;
382 if (signal_handlers[sig] == STG_SIG_DFL) {
383 continue; // handler has been changed.
386 info = stgMallocBytes(sizeof(siginfo_t), "startSignalHandlers");
387 // freed by runHandler
388 memcpy(info, next_pending_handler, sizeof(siginfo_t));
392 RtsFlags.GcFlags.initialStkSize,
395 &base_GHCziConc_runHandlers_closure,
396 rts_mkPtr(cap, info)),
397 rts_mkInt(cap, info->si_signo))));
400 unblockUserSignals();
404 /* ----------------------------------------------------------------------------
405 * Mark signal handlers during GC.
406 * -------------------------------------------------------------------------- */
409 markSignalHandlers (evac_fn evac STG_UNUSED, void *user STG_UNUSED)
414 #else /* !RTS_USER_SIGNALS */
416 stg_sig_install(StgInt sig STG_UNUSED,
417 StgInt spi STG_UNUSED,
418 void* mask STG_UNUSED)
420 //barf("User signals not supported");
426 #if defined(RTS_USER_SIGNALS)
427 /* -----------------------------------------------------------------------------
430 * We like to shutdown nicely after receiving a SIGINT, write out the
431 * stats, write profiling info, close open files and flush buffers etc.
432 * -------------------------------------------------------------------------- */
434 shutdown_handler(int sig STG_UNUSED)
436 // If we're already trying to interrupt the RTS, terminate with
437 // extreme prejudice. So the first ^C tries to exit the program
438 // cleanly, and the second one just kills it.
439 if (sched_state >= SCHED_INTERRUPTING) {
440 stg_exit(EXIT_INTERRUPTED);
446 /* -----------------------------------------------------------------------------
447 * Install default signal handlers.
449 * The RTS installs a default signal handler for catching
450 * SIGINT, so that we can perform an orderly shutdown.
452 * Haskell code may install their own SIGINT handler, which is
453 * fine, provided they're so kind as to put back the old one
454 * when they de-install.
456 * In addition to handling SIGINT, the RTS also handles SIGFPE
457 * by ignoring it. Apparently IEEE requires floating-point
458 * exceptions to be ignored by default, but alpha-dec-osf3
459 * doesn't seem to do so.
460 * -------------------------------------------------------------------------- */
462 initDefaultHandlers(void)
464 struct sigaction action,oact;
466 // install the SIGINT handler
467 action.sa_handler = shutdown_handler;
468 sigemptyset(&action.sa_mask);
470 if (sigaction(SIGINT, &action, &oact) != 0) {
471 sysErrorBelch("warning: failed to install SIGINT handler");
474 #if defined(HAVE_SIGINTERRUPT)
475 siginterrupt(SIGINT, 1); // isn't this the default? --SDM
478 // install the SIGFPE handler
480 // In addition to handling SIGINT, also handle SIGFPE by ignoring it.
481 // Apparently IEEE requires floating-point exceptions to be ignored by
482 // default, but alpha-dec-osf3 doesn't seem to do so.
484 // Commented out by SDM 2/7/2002: this causes an infinite loop on
485 // some architectures when an integer division by zero occurs: we
486 // don't recover from the floating point exception, and the
487 // program just generates another one immediately.
489 action.sa_handler = SIG_IGN;
490 sigemptyset(&action.sa_mask);
492 if (sigaction(SIGFPE, &action, &oact) != 0) {
493 sysErrorBelch("warning: failed to install SIGFPE handler");
497 #ifdef alpha_HOST_ARCH
498 ieee_set_fp_control(0);
501 // ignore SIGPIPE; see #1619
502 action.sa_handler = SIG_IGN;
503 sigemptyset(&action.sa_mask);
505 if (sigaction(SIGPIPE, &action, &oact) != 0) {
506 sysErrorBelch("warning: failed to install SIGPIPE handler");
511 resetDefaultHandlers(void)
513 struct sigaction action;
515 action.sa_handler = SIG_DFL;
516 sigemptyset(&action.sa_mask);
520 if (sigaction(SIGINT, &action, NULL) != 0) {
521 sysErrorBelch("warning: failed to uninstall SIGINT handler");
524 if (sigaction(SIGPIPE, &action, NULL) != 0) {
525 sysErrorBelch("warning: failed to uninstall SIGPIPE handler");
530 freeSignalHandlers(void) {
531 if (signal_handlers != NULL) {
532 stgFree(signal_handlers);
536 #endif /* RTS_USER_SIGNALS */