about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog9
-rw-r--r--Src/exec.c29
2 files changed, 33 insertions, 5 deletions
diff --git a/ChangeLog b/ChangeLog
index c5355ef50..ff4858d3d 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,10 @@
+2011-12-12  Peter Stephenson  <p.w.stephenson@ntlworld.com>
+
+	* 30000 plus a couple of comments: Src/exec.c: Better POSIXJOBS
+	behaviour: don't restore default behaviour for SIGTTOU etc. if
+	we're still doing job handling, and only continue with job
+	handling if this is a (...) subshell.
+
 2011-12-11  Peter Stephenson  <p.w.stephenson@ntlworld.com>
 
 	* discussed in 29984: Doc/Zsh/compsys.yo: use m+7 for files
@@ -15725,5 +15732,5 @@
 
 *****************************************************
 * This is used by the shell to define $ZSH_PATCHLEVEL
-* $Revision: 1.5536 $
+* $Revision: 1.5537 $
 *****************************************************
diff --git a/Src/exec.c b/Src/exec.c
index 2c644e6b7..9b3c50372 100644
--- a/Src/exec.c
+++ b/Src/exec.c
@@ -896,14 +896,16 @@ enum {
     /* Release the process group if pid is the shell's process group */
     ESUB_REVERTPGRP = 0x10,
     /* Don't handle the MONITOR option even if previously set */
-    ESUB_NOMONITOR = 0x20
+    ESUB_NOMONITOR = 0x20,
+    /* This is a subshell where job control is allowed */
+    ESUB_JOB_CONTROL = 0x40
 };
 
 /**/
 static void
 entersubsh(int flags)
 {
-    int sig, monitor;
+    int sig, monitor, job_control_ok;
 
     if (!(flags & ESUB_KEEPTRAP))
 	for (sig = 0; sig < VSIGCOUNT; sig++)
@@ -911,6 +913,7 @@ entersubsh(int flags)
 		sig != SIGDEBUG && sig != SIGZERR)
 		unsettrap(sig);
     monitor = isset(MONITOR);
+    job_control_ok = monitor && (flags & ESUB_JOB_CONTROL) && isset(POSIXJOBS);
     if (flags & ESUB_NOMONITOR)
 	opts[MONITOR] = 0;
     if (!isset(MONITOR)) {
@@ -938,6 +941,16 @@ entersubsh(int flags)
 	}
 	else if (!jobtab[thisjob].gleader ||
 		 setpgrp(0L, jobtab[thisjob].gleader) == -1) {
+	    /*
+	     * This is the standard point at which a newly started
+	     * process gets put into the foreground by taking over
+	     * the terminal.  Note that in normal circumstances we do
+	     * this only from the process itself.  This only works if
+	     * we are still ignoring SIGTTOU at this point; in this
+	     * case ignoring the signal has the special effect that
+	     * the operation is allowed to work (in addition to not
+	     * causing the shell to be suspended).
+	     */
 	    jobtab[thisjob].gleader = getpid();
 	    if (list_pipe_job != thisjob &&
 		!jobtab[list_pipe_job].gleader)
@@ -959,7 +972,13 @@ entersubsh(int flags)
     if ((flags & ESUB_REVERTPGRP) && getpid() == mypgrp)
 	release_pgrp();
     shout = NULL;
-    if (isset(MONITOR)) {
+    if (!job_control_ok) {
+	/*
+	 * If this process is not goign to be doing job control,
+	 * we don't want to do special things with the corresponding
+	 * signals.  If it is, we need to keep the special behaviour:
+	 * see note about attachtty() above.
+	 */
 	signal_default(SIGTTOU);
 	signal_default(SIGTTIN);
 	signal_default(SIGTSTP);
@@ -971,7 +990,7 @@ entersubsh(int flags)
     }
     if (!(sigtrapped[SIGQUIT] & ZSIG_IGNORED))
 	signal_default(SIGQUIT);
-    if (!isset(POSIXJOBS))
+    if (!job_control_ok)
 	opts[MONITOR] = 0;
     opts[USEZLE] = 0;
     zleactive = 0;
@@ -2829,6 +2848,8 @@ execcmd(Estate state, int input, int output, int how, int last1)
 	flags = ((how & Z_ASYNC) ? ESUB_ASYNC : 0) | ESUB_PGRP;
 	if ((type != WC_SUBSH) && !(how & Z_ASYNC))
 	    flags |= ESUB_KEEPTRAP;
+	if (type == WC_SUBSH && !(how & Z_ASYNC))
+	    flags |= ESUB_JOB_CONTROL;
 	entersubsh(flags);
 	close(synch[1]);
 	forked = 1;