summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog9
-rw-r--r--Src/jobs.c4
-rw-r--r--Src/signals.c31
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