diff options
-rw-r--r-- | ChangeLog | 9 | ||||
-rw-r--r-- | Src/jobs.c | 4 | ||||
-rw-r--r-- | Src/signals.c | 31 |
3 files changed, 30 insertions, 14 deletions
diff --git a/ChangeLog b/ChangeLog index 2dc28a2cb..ec31a691a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +2009-07-19 Barton E. Schaefer <schaefer@zsh.org> + + * 27169: Src/jobs.c, Src/signals.c: 23067 went too far in opening + up the signal mask when waiting for jobs; an interrupt from the + terminal should not terminate the shell until the foreground job + has a chance to exit or to choose not to do so. + 2009-07-19 Peter Stephenson <p.w.stephenson@ntlworld.com> * 27167: Src/builtin.c, Src/options.c, Src/zsh.h, @@ -12011,5 +12018,5 @@ ***************************************************** * This is used by the shell to define $ZSH_PATCHLEVEL -* $Revision: 1.4745 $ +* $Revision: 1.4746 $ ***************************************************** diff --git a/Src/jobs.c b/Src/jobs.c index df7d9d689..d5658d2eb 100644 --- a/Src/jobs.c +++ b/Src/jobs.c @@ -1191,7 +1191,7 @@ waitforpid(pid_t pid, int wait_cmd) kill(pid, SIGCONT); last_signal = -1; - signal_suspend(SIGCHLD); + signal_suspend(SIGCHLD, wait_cmd); if (last_signal != SIGCHLD && wait_cmd && last_signal >= 0 && (sigtrapped[last_signal] & ZSIG_TRAPPED)) { /* wait command interrupted, but no error: return */ @@ -1230,7 +1230,7 @@ zwaitjob(int job, int wait_cmd) while (!errflag && jn->stat && !(jn->stat & STAT_DONE) && !(interact && (jn->stat & STAT_STOPPED))) { - signal_suspend(SIGCHLD); + signal_suspend(SIGCHLD, wait_cmd); if (last_signal != SIGCHLD && wait_cmd && last_signal >= 0 && (sigtrapped[last_signal] & ZSIG_TRAPPED)) { diff --git a/Src/signals.c b/Src/signals.c index 723b121a8..4bc1de016 100644 --- a/Src/signals.c +++ b/Src/signals.c @@ -342,29 +342,38 @@ static signal_jmp_buf suspend_jmp_buf; /**/ int -signal_suspend(UNUSED(int sig)) +signal_suspend(UNUSED(int sig), int wait_cmd) { int ret; - -#ifdef POSIX_SIGNALS + +#if defined(POSIX_SIGNALS) || defined(BSD_SIGNALS) sigset_t set; -#ifdef BROKEN_POSIX_SIGSUSPEND +# if defined(POSIX_SIGNALS) && defined(BROKEN_POSIX_SIGSUSPEND) sigset_t oset; -#endif /* BROKEN_POSIX_SIGSUSPEND */ +# endif sigemptyset(&set); -#ifdef BROKEN_POSIX_SIGSUSPEND + + /* SIGINT from the terminal driver needs to interrupt "wait" + * and to cause traps to fire, but otherwise should not be + * handled by the shell until after any foreground job has + * a chance to decide whether to exit on that signal. + */ + if (!(wait_cmd || isset(TRAPSASYNC) || + (sigtrapped[SIGINT] & ~ZSIG_IGNORED))) + sigaddset(&set, SIGINT); +#endif /* POSIX_SIGNALS || BSD_SIGNALS */ + +#ifdef POSIX_SIGNALS +# ifdef BROKEN_POSIX_SIGSUSPEND sigprocmask(SIG_SETMASK, &set, &oset); pause(); sigprocmask(SIG_SETMASK, &oset, NULL); -#else /* not BROKEN_POSIX_SIGSUSPEND */ +# else /* not BROKEN_POSIX_SIGSUSPEND */ ret = sigsuspend(&set); -#endif /* BROKEN_POSIX_SIGSUSPEND */ +# endif /* BROKEN_POSIX_SIGSUSPEND */ #else /* not POSIX_SIGNALS */ # ifdef BSD_SIGNALS - sigset_t set; - - sigemptyset(&set); ret = sigpause(set); # else # ifdef SYSV_SIGNALS |