diff options
Diffstat (limited to 'signal.c')
| -rw-r--r-- | signal.c | 53 |
1 files changed, 37 insertions, 16 deletions
@@ -2,32 +2,51 @@ #include <signal.h> #include <setjmp.h> + #include "rc.h" #include "sigmsgs.h" #include "jbwrap.h" -Jbwrap slowbuf; -volatile SIG_ATOMIC_T slow, interrupt_happened; +#if HAVE_SA_INTERRUPT +static void (*sys_signal(int signum, void (*handler)(int)))(int) { + struct sigaction new, old; + + new.sa_handler = handler; + new.sa_flags = SA_INTERRUPT; + sigaction(signum, &new, &old); + return old.sa_handler; +} +#else +#define sys_signal signal +#endif + void (*sighandlers[NUMOFSIGNALS])(int); -static volatile SIG_ATOMIC_T sigcount, caught[NUMOFSIGNALS]; +static volatile sig_atomic_t sigcount, caught[NUMOFSIGNALS]; extern void catcher(int s) { if (caught[s] == 0) { sigcount++; caught[s] = 1; } - signal(s, catcher); - interrupt_happened = TRUE; -#ifndef HAVE_RESTARTABLE_SYSCALLS - if (slow) - longjmp(slowbuf.j, 1); + sys_signal(s, catcher); + +#if READLINE + if (rl_active) + siglongjmp(rl_buf.j, s); +#endif /* READLINE */ + +#if HAVE_RESTARTABLE_SYSCALLS + if (slow) { + siglongjmp(slowbuf.j, s); +} #endif } extern void sigchk() { void (*h)(int); int s, i; + if (sigcount == 0) return; /* ho hum; life as usual */ if (forked) @@ -53,11 +72,11 @@ extern void (*rc_signal(int s, void (*h)(int)))(int) { sigchk(); old = sighandlers[s]; if (h == SIG_DFL || h == SIG_IGN) { - signal(s, h); sighandlers[s] = h; + sys_signal(s, h); } else { sighandlers[s] = h; - signal(s, catcher); + sys_signal(s, catcher); } return old; } @@ -65,16 +84,18 @@ extern void (*rc_signal(int s, void (*h)(int)))(int) { extern void initsignal() { void (*h)(int); int i; + for (i = 1; i < NUMOFSIGNALS; i++) { - if ((h = signal(i, SIG_DFL)) != SIG_DFL) - signal(i, h); + h = sys_signal(i, SIG_DFL); + if (h != SIG_DFL && h != SIG_ERR) + sys_signal(i, h); sighandlers[i] = h; } -#ifdef SIGCLD +#if HAVE_SYSV_SIGCLD /* Ensure that SIGCLD is not SIG_IGN. Solaris's rshd does this. :-( */ - h = signal(SIGCLD, SIG_DFL); - if (h != SIG_IGN) - signal(SIGCLD, h); + h = sys_signal(SIGCLD, SIG_DFL); + if (h != SIG_IGN && h != SIG_ERR) + sys_signal(SIGCLD, h); #endif } |