/* Need to define sig2interrupt vector. ** Interrupt-system mutators should probably hold interrupts while they ** operate. */ #include #include #include #include #include #include "cstuff.h" /* Make sure our exports match up w/the implementation: */ #include "sighandlers1.h" /* Import the OS-dependent set of signals and their translations ** to S48 vm interrupts. */ #include "signals1.h" extern scheme_value Spending_interruptsS, Sinterrupt_handlersS; /* Translate Unix signal numbers to S48 interrupt numbers. */ int sig2interrupt(int signal) { return ( signal < 0 || signal > max_sig ) ? -1 : sig2int[signal]; } /* Hack the blocked-signal mask. ******************************************************************************* */ #include "machine/sigset.h" int set_procmask(int hi, int lo, int *old_lo_p) { sigset_t mask, old_mask; int old_hi; make_sigset(&mask, hi, lo); sigprocmask(SIG_SETMASK, &mask, &old_mask); split_sigset(old_mask, &old_hi, old_lo_p); return old_hi; } int get_procmask(int *old_lo_p) { sigset_t old_mask; int old_hi; sigprocmask(SIG_SETMASK, NULL, &old_mask); split_sigset(old_mask, &old_hi, old_lo_p); return old_hi; } /* Set/Get signal handlers ******************************************************************************* */ static void scm_handle_sig(int sig) { /*fprintf(stderr, "scm_handle_sig(%d) = int %d\n", sig, sig2int[sig]);*/ Spending_interruptsS |= (1< ignore, 1 => default, 2 => S48 VM */ /* Common code for two functions above. */ static scheme_value scsh_ret_sig(int retval, struct sigaction *oldsa, int *old_hc, int *oflags) { if( retval ) { *old_hc = -1; *oflags = -1; return ENTER_FIXNUM(errno); } if( oldsa->sa_handler == SIG_IGN ) *old_hc = 0; else if( oldsa->sa_handler == SIG_DFL ) *old_hc = 1; else if( oldsa->sa_handler == scm_handle_sig ) *old_hc = 2; else *old_hc = ENTER_FIXNUM(3); /* Unknown signal handler. */ *oflags = oldsa->sa_flags; return SCHFALSE; } scheme_value scsh_set_sig(int sig, int handler_code, int flags, int *old_hc, int *oflags) { struct sigaction new, old; sigemptyset(&new.sa_mask); /* WTF */ new.sa_flags = flags; switch( handler_code ) { case 0: new.sa_handler = SIG_IGN; break; case 1: new.sa_handler = SIG_DFL; break; case 2: new.sa_handler = scm_handle_sig; break; default: fprintf(stderr, "Impossible handler_code in set_sig_handler: %d\n", handler_code); exit(-1); } return scsh_ret_sig(sigaction(sig, &new, &old), &old, old_hc, oflags); } scheme_value scsh_get_sig(int signal, int *old_hc, int *oflags) { struct sigaction old; return scsh_ret_sig(sigaction(signal, NULL, &old), &old, old_hc, oflags); } /* This guy is responsible for making the default action for a ** Unix signal happen. Because S48's signal handler system is ** interposed between delivery-to-the-process and ** delivery-to-the-scheme-handler, when the user sets a signal ** handler to default, we install a Scheme proc that calls this ** guy, instead of just slapping a SIGDFL in as the Unix handler. ** We only have to do this for signals whose default isn't "ignore," i.e.: ** Posix: SIGALRM SIGHUP SIGINT SIGQUIT SIGTERM SIGUSR1 SIGUSR2 ** Non-Posix: SIGINFO SIGPOLL SIGPROF SIGVTALRM SIGXCPU SIGXFSZ SIGIO ** This way, the S48 signal-blocking mechanism can work. ** ** Weird, I know. */ void do_default_sigaction(int signal) { sigset_t ss, old_ss; struct sigaction default_action, old_action; /* fprintf(stderr, "Doing default for signal %d\n", signal); */ sigfillset(&ss); /* Block everyone. */ sigprocmask(SIG_SETMASK, &ss, &old_ss); default_action.sa_handler = SIG_DFL; /* Set for default. */ sigemptyset(&default_action.sa_mask); default_action.sa_flags = 0; sigaction(signal, &default_action, &old_action); raise(signal); /* Raise the signal. */ sigdelset(&ss, signal); sigprocmask(SIG_SETMASK, &ss, 0); /* Handle it. */ /* Most likely, we'll never get to here, as the default for ** the signals we're handling is "terminate," but we'll play it safe. */ sigaction(signal, &old_action, 0); /* Restore old handler, */ sigprocmask(SIG_SETMASK, &old_ss, 0); /* and mask. */ } /* Set up the Unix signal system the way we want it for scsh. */ void install_scsh_handlers(void) { struct sigaction new; int i; sigemptyset(&new.sa_mask); /* WTF */ new.sa_handler = scm_handle_sig; new.sa_flags = 0; for(i=max_sig; i>=0; i--) if( sig2int[i] >= 0 ) { /* This is a signal we want the S48 interrupt system to handle. */ sigaction(i, &new, 0); } /* Turn off SIGPIPE and SIGSYS -- they are handled by synchronous exceptions ** triggered by errno returns. */ new.sa_handler = SIG_IGN; sigaction(SIGPIPE, &new, 0); #ifdef SIGSYS sigaction(SIGSYS, &new, 0); #endif } /* Sneak me the S48 interrupt handlers vector. */ scheme_value get_int_handlers(void) { return Sinterrupt_handlersS; }