/* -----------------------------------------------------------------------------
- * $Id: Signals.c,v 1.23 2002/03/12 13:57:14 simonmar Exp $
+ * $Id: Signals.c,v 1.30 2002/12/05 14:20:55 stolz Exp $
*
* (c) The GHC Team, 1998-1999
*
#include "StablePriv.h"
#ifdef alpha_TARGET_ARCH
-#include <machine/fpu.h>
+# include <machine/fpu.h>
#endif
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#endif
+
+#ifdef HAVE_SIGNAL_H
+# include <signal.h>
+#endif
+
+#include <stdlib.h>
+
#ifndef mingw32_TARGET_OS
#ifndef PAR
* Install a Haskell signal handler.
* -------------------------------------------------------------------------- */
-StgInt
-stg_sig_install(StgInt sig, StgInt spi, StgStablePtr handler, sigset_t *mask)
+int
+stg_sig_install(int sig, int spi, StgStablePtr *handler, void *mask)
{
- sigset_t signals;
+ sigset_t signals, osignals;
struct sigaction action;
StgInt previous_spi;
// Block the signal until we figure out what to do
// Count on this to fail if the signal number is invalid
if (sig < 0 || sigemptyset(&signals) ||
- sigaddset(&signals, sig) || sigprocmask(SIG_BLOCK, &signals, NULL)) {
+ sigaddset(&signals, sig) || sigprocmask(SIG_BLOCK, &signals, &osignals)) {
return STG_SIG_ERR;
}
break;
case STG_SIG_HAN:
- handlers[sig] = (StgInt)handler;
+ case STG_SIG_RST:
+ handlers[sig] = (StgInt)*handler;
sigaddset(&userSignals, sig);
action.sa_handler = generic_handler;
+ if (spi == STG_SIG_RST) {
+ action.sa_flags = SA_RESETHAND;
+ }
n_haskell_handlers++;
break;
barf("stg_sig_install: bad spi");
}
- if (mask != 0)
- action.sa_mask = *mask;
+ if (mask != NULL)
+ action.sa_mask = *(sigset_t *)mask;
else
sigemptyset(&action.sa_mask);
- action.sa_flags = sig == SIGCHLD && nocldstop ? SA_NOCLDSTOP : 0;
+ action.sa_flags |= sig == SIGCHLD && nocldstop ? SA_NOCLDSTOP : 0;
if (sigaction(sig, &action, NULL) ||
- sigprocmask(SIG_UNBLOCK, &signals, NULL))
+ sigprocmask(SIG_SETMASK, &osignals, NULL))
{
// need to return an error code, so avoid a stable pointer leak
// by freeing the previous handler if there was one.
return STG_SIG_ERR;
}
- return previous_spi;
+ if (previous_spi == STG_SIG_DFL || previous_spi == STG_SIG_IGN
+ || previous_spi == STG_SIG_ERR) {
+ return previous_spi;
+ } else {
+ *handler = (StgStablePtr)previous_spi;
+ return STG_SIG_HAN;
+ }
}
/* -----------------------------------------------------------------------------
unblockUserSignals();
}
+/* ----------------------------------------------------------------------------
+ * Mark signal handlers during GC.
+ *
+ * We do this rather than trying to start all the signal handlers
+ * prior to GC, because that requires extra heap for the new threads.
+ * Signals must be blocked (see blockUserSignals() above) during GC to
+ * avoid race conditions.
+ * -------------------------------------------------------------------------- */
+
+void
+markSignalHandlers (evac_fn evac)
+{
+ StgPtr *p;
+
+ p = next_pending_handler;
+ while (p != pending_handler_buf) {
+ p--;
+ evac((StgClosure **)p);
+ }
+}
+
#else // PAR
StgInt
stg_sig_install(StgInt sig, StgInt spi, StgStablePtr handler, sigset_t *mask)
prog_belch("warning: failed to install SIGINT handler");
}
+#ifndef cygwin32_TARGET_OS
siginterrupt(SIGINT, 1); // isn't this the default? --SDM
+#endif
// install the SIGCONT handler
action.sa_handler = cont_handler;
}
// install the SIGFPE handler
+
+ // In addition to handling SIGINT, also handle SIGFPE by ignoring it.
+ // Apparently IEEE requires floating-point exceptions to be ignored by
+ // default, but alpha-dec-osf3 doesn't seem to do so.
+
+ // Commented out by SDM 2/7/2002: this causes an infinite loop on
+ // some architectures when an integer division by zero occurs: we
+ // don't recover from the floating point exception, and the
+ // program just generates another one immediately.
+#if 0
action.sa_handler = SIG_IGN;
sigemptyset(&action.sa_mask);
action.sa_flags = 0;
if (sigaction(SIGFPE, &action, &oact) != 0) {
prog_belch("warning: failed to install SIGFPE handler");
}
+#endif
+
#ifdef alpha_TARGET_ARCH
ieee_set_fp_control(0);
#endif