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,
158 #if defined(THREADED_RTS)
160 if (io_manager_pipe != -1)
162 StgWord8 buf[sizeof(siginfo_t) + 1];
166 memcpy(buf+1, info, sizeof(siginfo_t));
167 r = write(io_manager_pipe, buf, sizeof(siginfo_t)+1);
168 if (r == -1 && errno == EAGAIN)
170 errorBelch("lost signal due to full pipe: %d\n", sig);
173 // If the IO manager hasn't told us what the FD of the write end
174 // of its pipe is, there's not much we can do here, so just ignore
177 #else /* not THREADED_RTS */
179 /* Can't call allocate from here. Probably can't call malloc
180 either. However, we have to schedule a new thread somehow.
182 It's probably ok to request a context switch and allow the
183 scheduler to start the handler thread, but how do we
184 communicate this to the scheduler?
186 We need some kind of locking, but with low overhead (i.e. no
187 blocking signals every time around the scheduler).
189 Signal Handlers are atomic (i.e. they can't be interrupted), and
190 we can make use of this. We just need to make sure the
191 critical section of the scheduler can't be interrupted - the
192 only way to do this is to block signals. However, we can lower
193 the overhead by only blocking signals when there are any
194 handlers to run, i.e. the set of pending handlers is
198 /* We use a stack to store the pending signals. We can't
199 dynamically grow this since we can't allocate any memory from
200 within a signal handler.
202 Hence unfortunately we have to bomb out if the buffer
203 overflows. It might be acceptable to carry on in certain
204 circumstances, depending on the signal.
207 memcpy(next_pending_handler, info, sizeof(siginfo_t));
209 next_pending_handler++;
212 if (next_pending_handler == &pending_handler_buf[N_PENDING_HANDLERS]) {
213 errorBelch("too many pending signals");
214 stg_exit(EXIT_FAILURE);
217 contextSwitchCapability(&MainCapability);
219 #endif /* THREADED_RTS */
222 /* -----------------------------------------------------------------------------
223 * Blocking/Unblocking of the user signals
224 * -------------------------------------------------------------------------- */
226 static sigset_t userSignals;
227 static sigset_t savedSignals;
230 initUserSignals(void)
232 sigemptyset(&userSignals);
234 getStablePtr((StgPtr)&base_GHCziConc_runHandlers_closure);
235 // needed to keep runHandler alive
240 blockUserSignals(void)
242 sigprocmask(SIG_BLOCK, &userSignals, &savedSignals);
246 unblockUserSignals(void)
248 sigprocmask(SIG_SETMASK, &savedSignals, NULL);
252 anyUserHandlers(void)
254 return n_haskell_handlers != 0;
257 #if !defined(THREADED_RTS)
259 awaitUserSignals(void)
261 while (!signals_pending() && sched_state == SCHED_RUNNING) {
267 /* -----------------------------------------------------------------------------
268 * Install a Haskell signal handler.
270 * We should really do this in Haskell in GHC.Conc, and share the
271 * signal_handlers array with the one there.
273 * -------------------------------------------------------------------------- */
276 stg_sig_install(int sig, int spi, void *mask)
278 sigset_t signals, osignals;
279 struct sigaction action;
282 // Block the signal until we figure out what to do
283 // Count on this to fail if the signal number is invalid
284 if (sig < 0 || sigemptyset(&signals) ||
285 sigaddset(&signals, sig) || sigprocmask(SIG_BLOCK, &signals, &osignals)) {
291 previous_spi = signal_handlers[sig];
297 action.sa_handler = SIG_IGN;
301 action.sa_handler = SIG_DFL;
305 action.sa_flags |= SA_RESETHAND;
308 action.sa_sigaction = generic_handler;
309 action.sa_flags |= SA_SIGINFO;
313 barf("stg_sig_install: bad spi");
317 action.sa_mask = *(sigset_t *)mask;
319 sigemptyset(&action.sa_mask);
321 action.sa_flags |= sig == SIGCHLD && nocldstop ? SA_NOCLDSTOP : 0;
323 if (sigaction(sig, &action, NULL))
325 errorBelch("sigaction");
329 signal_handlers[sig] = spi;
334 sigaddset(&userSignals, sig);
335 if (previous_spi != STG_SIG_HAN && previous_spi != STG_SIG_RST) {
336 n_haskell_handlers++;
341 sigdelset(&userSignals, sig);
342 if (previous_spi == STG_SIG_HAN || previous_spi == STG_SIG_RST) {
343 n_haskell_handlers--;
348 if (sigprocmask(SIG_SETMASK, &osignals, NULL))
350 errorBelch("sigprocmask");
357 /* -----------------------------------------------------------------------------
358 * Creating new threads for signal handlers.
359 * -------------------------------------------------------------------------- */
361 #if !defined(THREADED_RTS)
363 startSignalHandlers(Capability *cap)
370 while (next_pending_handler != pending_handler_buf) {
372 next_pending_handler--;
374 sig = next_pending_handler->si_signo;
375 if (signal_handlers[sig] == STG_SIG_DFL) {
376 continue; // handler has been changed.
379 info = stgMallocBytes(sizeof(siginfo_t), "startSignalHandlers");
380 // freed by runHandler
381 memcpy(info, next_pending_handler, sizeof(siginfo_t));
385 RtsFlags.GcFlags.initialStkSize,
388 &base_GHCziConc_runHandlers_closure,
389 rts_mkPtr(cap, info)),
390 rts_mkInt(cap, info->si_signo))));
393 unblockUserSignals();
397 /* ----------------------------------------------------------------------------
398 * Mark signal handlers during GC.
399 * -------------------------------------------------------------------------- */
402 markSignalHandlers (evac_fn evac STG_UNUSED, void *user STG_UNUSED)
407 #else /* !RTS_USER_SIGNALS */
409 stg_sig_install(StgInt sig STG_UNUSED,
410 StgInt spi STG_UNUSED,
411 void* mask STG_UNUSED)
413 //barf("User signals not supported");
419 #if defined(RTS_USER_SIGNALS)
420 /* -----------------------------------------------------------------------------
423 * We like to shutdown nicely after receiving a SIGINT, write out the
424 * stats, write profiling info, close open files and flush buffers etc.
425 * -------------------------------------------------------------------------- */
427 shutdown_handler(int sig STG_UNUSED)
429 // If we're already trying to interrupt the RTS, terminate with
430 // extreme prejudice. So the first ^C tries to exit the program
431 // cleanly, and the second one just kills it.
432 if (sched_state >= SCHED_INTERRUPTING) {
433 stg_exit(EXIT_INTERRUPTED);
439 /* -----------------------------------------------------------------------------
440 * Install default signal handlers.
442 * The RTS installs a default signal handler for catching
443 * SIGINT, so that we can perform an orderly shutdown.
445 * Haskell code may install their own SIGINT handler, which is
446 * fine, provided they're so kind as to put back the old one
447 * when they de-install.
449 * In addition to handling SIGINT, the RTS also handles SIGFPE
450 * by ignoring it. Apparently IEEE requires floating-point
451 * exceptions to be ignored by default, but alpha-dec-osf3
452 * doesn't seem to do so.
453 * -------------------------------------------------------------------------- */
455 initDefaultHandlers(void)
457 struct sigaction action,oact;
459 // install the SIGINT handler
460 action.sa_handler = shutdown_handler;
461 sigemptyset(&action.sa_mask);
463 if (sigaction(SIGINT, &action, &oact) != 0) {
464 sysErrorBelch("warning: failed to install SIGINT handler");
467 #if defined(HAVE_SIGINTERRUPT)
468 siginterrupt(SIGINT, 1); // isn't this the default? --SDM
471 // install the SIGFPE handler
473 // In addition to handling SIGINT, also handle SIGFPE by ignoring it.
474 // Apparently IEEE requires floating-point exceptions to be ignored by
475 // default, but alpha-dec-osf3 doesn't seem to do so.
477 // Commented out by SDM 2/7/2002: this causes an infinite loop on
478 // some architectures when an integer division by zero occurs: we
479 // don't recover from the floating point exception, and the
480 // program just generates another one immediately.
482 action.sa_handler = SIG_IGN;
483 sigemptyset(&action.sa_mask);
485 if (sigaction(SIGFPE, &action, &oact) != 0) {
486 sysErrorBelch("warning: failed to install SIGFPE handler");
490 #ifdef alpha_HOST_ARCH
491 ieee_set_fp_control(0);
494 // ignore SIGPIPE; see #1619
495 action.sa_handler = SIG_IGN;
496 sigemptyset(&action.sa_mask);
498 if (sigaction(SIGPIPE, &action, &oact) != 0) {
499 sysErrorBelch("warning: failed to install SIGPIPE handler");
504 resetDefaultHandlers(void)
506 struct sigaction action;
508 action.sa_handler = SIG_DFL;
509 sigemptyset(&action.sa_mask);
513 if (sigaction(SIGINT, &action, NULL) != 0) {
514 sysErrorBelch("warning: failed to uninstall SIGINT handler");
517 if (sigaction(SIGPIPE, &action, NULL) != 0) {
518 sysErrorBelch("warning: failed to uninstall SIGPIPE handler");
523 freeSignalHandlers(void) {
524 if (signal_handlers != NULL) {
525 stgFree(signal_handlers);
529 #endif /* RTS_USER_SIGNALS */