X-Git-Url: http://git.megacz.com/?a=blobdiff_plain;f=rts%2Fposix%2FSignals.c;h=e34190c4393790f80c6880a2835a8af1382b3b55;hb=a200038f469418fef77d863dc3d1cd0125ec1e82;hp=5f5f77fd39fd6d40b1b7b5894ab7e7c0026a32c6;hpb=0065d5ab628975892cea1ec7303f968c3338cbe1;p=ghc-hetmet.git diff --git a/rts/posix/Signals.c b/rts/posix/Signals.c index 5f5f77f..e34190c 100644 --- a/rts/posix/Signals.c +++ b/rts/posix/Signals.c @@ -16,6 +16,8 @@ #include "posix/Signals.h" #include "RtsUtils.h" #include "RtsFlags.h" +#include "Prelude.h" +#include "ThrIOManager.h" #ifdef alpha_HOST_ARCH # if defined(linux_HOST_OS) @@ -39,7 +41,7 @@ * to POSIX.1 to control whether or not to include SA_NOCLDSTOP when * installing a SIGCHLD handler. */ -StgInt nocldstop = 0; +HsInt nocldstop = 0; /* ----------------------------------------------------------------------------- * The table of signal handlers @@ -107,6 +109,9 @@ more_handlers(I_ sig) // Here's the pipe into which we will send our signals static int io_manager_pipe = -1; +#define IO_MANAGER_WAKEUP 0xff +#define IO_MANAGER_DIE 0xfe + void setIOManagerPipe (int fd) { @@ -115,6 +120,40 @@ setIOManagerPipe (int fd) io_manager_pipe = fd; } +#if defined(THREADED_RTS) +void +ioManagerWakeup (void) +{ + // Wake up the IO Manager thread by sending a byte down its pipe + if (io_manager_pipe >= 0) { + StgWord8 byte = (StgWord8)IO_MANAGER_WAKEUP; + write(io_manager_pipe, &byte, 1); + } +} + +void +ioManagerDie (void) +{ + // Ask the IO Manager thread to exit + if (io_manager_pipe >= 0) { + StgWord8 byte = (StgWord8)IO_MANAGER_DIE; + write(io_manager_pipe, &byte, 1); + } +} + +void +ioManagerStart (void) +{ + // Make sure the IO manager thread is running + Capability *cap; + if (io_manager_pipe < 0) { + cap = rts_lock(); + rts_evalIO(cap,&base_GHCziConc_ensureIOManagerIsRunning_closure,NULL); + rts_unlock(cap); + } +} +#endif + #if !defined(THREADED_RTS) #define N_PENDING_HANDLERS 16 @@ -125,22 +164,6 @@ StgPtr *next_pending_handler = pending_handler_buf; #endif /* THREADED_RTS */ /* ----------------------------------------------------------------------------- - * SIGCONT handler - * - * It seems that shells tend to put stdin back into blocking mode - * following a suspend/resume of the process. Here we arrange to put - * it back into non-blocking mode. We don't do anything to - * stdout/stderr because these handles don't get put into non-blocking - * mode at all - see the comments on stdout/stderr in PrelHandle.hsc. - * -------------------------------------------------------------------------- */ - -static void -cont_handler(int sig STG_UNUSED) -{ - setNonBlockingFd(0); -} - -/* ----------------------------------------------------------------------------- * Low-level signal handler * * Places the requested handler on a stack of pending handlers to be @@ -210,11 +233,6 @@ generic_handler(int sig) sigaddset(&signals, sig); sigprocmask(SIG_UNBLOCK, &signals, NULL); - // *always* do the SIGCONT handler, even if the user overrides it. - if (sig == SIGCONT) { - cont_handler(sig); - } - context_switch = 1; } @@ -374,19 +392,19 @@ startSignalHandlers(Capability *cap) #if !defined(THREADED_RTS) void -markSignalHandlers (evac_fn evac) +markSignalHandlers (evac_fn evac, void *user) { StgPtr *p; p = next_pending_handler; while (p != pending_handler_buf) { p--; - evac((StgClosure **)p); + evac(user, (StgClosure **)p); } } #else void -markSignalHandlers (evac_fn evac STG_UNUSED) +markSignalHandlers (evac_fn evac STG_UNUSED, void *user STG_UNUSED) { } #endif @@ -411,24 +429,9 @@ stg_sig_install(StgInt sig STG_UNUSED, * We like to shutdown nicely after receiving a SIGINT, write out the * stats, write profiling info, close open files and flush buffers etc. * -------------------------------------------------------------------------- */ -#ifdef SMP -pthread_t startup_guy; -#endif - static void shutdown_handler(int sig STG_UNUSED) { -#ifdef SMP - // if I'm a worker thread, send this signal to the guy who - // originally called startupHaskell(). Since we're handling - // the signal, it won't be a "send to all threads" type of signal - // (according to the POSIX threads spec). - if (pthread_self() != startup_guy) { - pthread_kill(startup_guy, sig); - return; - } -#endif - // If we're already trying to interrupt the RTS, terminate with // extreme prejudice. So the first ^C tries to exit the program // cleanly, and the second one just kills it. @@ -455,34 +458,22 @@ shutdown_handler(int sig STG_UNUSED) * doesn't seem to do so. * -------------------------------------------------------------------------- */ void -initDefaultHandlers() +initDefaultHandlers(void) { struct sigaction action,oact; -#ifdef SMP - startup_guy = pthread_self(); -#endif - // install the SIGINT handler action.sa_handler = shutdown_handler; sigemptyset(&action.sa_mask); action.sa_flags = 0; if (sigaction(SIGINT, &action, &oact) != 0) { - errorBelch("warning: failed to install SIGINT handler"); + sysErrorBelch("warning: failed to install SIGINT handler"); } #if defined(HAVE_SIGINTERRUPT) siginterrupt(SIGINT, 1); // isn't this the default? --SDM #endif - // install the SIGCONT handler - action.sa_handler = cont_handler; - sigemptyset(&action.sa_mask); - action.sa_flags = 0; - if (sigaction(SIGCONT, &action, &oact) != 0) { - errorBelch("warning: failed to install SIGCONT handler"); - } - // install the SIGFPE handler // In addition to handling SIGINT, also handle SIGFPE by ignoring it. @@ -498,13 +489,47 @@ initDefaultHandlers() sigemptyset(&action.sa_mask); action.sa_flags = 0; if (sigaction(SIGFPE, &action, &oact) != 0) { - errorBelch("warning: failed to install SIGFPE handler"); + sysErrorBelch("warning: failed to install SIGFPE handler"); } #endif #ifdef alpha_HOST_ARCH ieee_set_fp_control(0); #endif + + // ignore SIGPIPE; see #1619 + action.sa_handler = SIG_IGN; + sigemptyset(&action.sa_mask); + action.sa_flags = 0; + if (sigaction(SIGPIPE, &action, &oact) != 0) { + sysErrorBelch("warning: failed to install SIGPIPE handler"); + } +} + +void +resetDefaultHandlers(void) +{ + struct sigaction action; + + action.sa_handler = SIG_DFL; + sigemptyset(&action.sa_mask); + action.sa_flags = 0; + + // restore SIGINT + if (sigaction(SIGINT, &action, NULL) != 0) { + sysErrorBelch("warning: failed to uninstall SIGINT handler"); + } + // restore SIGPIPE + if (sigaction(SIGPIPE, &action, NULL) != 0) { + sysErrorBelch("warning: failed to uninstall SIGPIPE handler"); + } +} + +void +freeSignalHandlers(void) { + if (signal_handlers != NULL) { + stgFree(signal_handlers); + } } #endif /* RTS_USER_SIGNALS */