about summary refs log tree commit diff
path: root/Src
diff options
context:
space:
mode:
Diffstat (limited to 'Src')
-rw-r--r--Src/exec.c16
-rw-r--r--Src/jobs.c19
-rw-r--r--Src/zsh.h1
3 files changed, 31 insertions, 5 deletions
diff --git a/Src/exec.c b/Src/exec.c
index b076f4af9..c9c895940 100644
--- a/Src/exec.c
+++ b/Src/exec.c
@@ -949,9 +949,10 @@ execpline(Estate state, wordcode slcode, int how, int last1)
 
 		    /* If the super-job contains only the sub-shell, the
 		       sub-shell is the group leader. */
-		    if (!jn->procs->next || lpforked == 2)
+		    if (!jn->procs->next || lpforked == 2) {
 			jn->gleader = list_pipe_pid;
-
+			jn->stat |= STAT_SUBLEADER;
+		    }
 		    for (pn = jobtab[jn->other].procs; pn; pn = pn->next)
 			if (WIFSTOPPED(pn->status))
 			    break;
@@ -971,14 +972,17 @@ execpline(Estate state, wordcode slcode, int how, int last1)
 		    lastwj = -1;
 	    }
 
+	    errbrk_saved = 0;
 	    for (; !nowait;) {
 		if (list_pipe_child) {
 		    jn->stat |= STAT_NOPRINT;
 		    makerunning(jn);
 		}
-		if (!(jn->stat & STAT_LOCKED))
+		if (!(jn->stat & STAT_LOCKED)) {
+		    child_unblock();
+		    child_block();
 		    waitjobs();
-
+		}
 		if (list_pipe_child &&
 		    jn->stat & STAT_DONE &&
 		    lastval2 & 0200)
@@ -1042,6 +1046,10 @@ execpline(Estate state, wordcode slcode, int how, int last1)
 			list_pipe = 0;
 			list_pipe_child = 1;
 			opts[INTERACTIVE] = 0;
+			if (errbrk_saved) {
+			    errflag = prev_errflag;
+			    breaks = prev_breaks;
+			}
 			break;
 		    }
 		}
diff --git a/Src/jobs.c b/Src/jobs.c
index e66d3b3fd..d519da00c 100644
--- a/Src/jobs.c
+++ b/Src/jobs.c
@@ -64,7 +64,13 @@ struct tms shtms;
  
 /**/
 int ttyfrozen;
- 
+
+/* Previous values of errflag and breaks if the signal handler had to
+ * change them. And a flag saying if it did that. */
+
+/**/
+int prev_errflag, prev_breaks, errbrk_saved;
+
 static struct timeval dtimeval, now;
 
 /* Diff two timevals for elapsed-time computations */
@@ -311,6 +317,11 @@ update_job(Job jn)
 		/* If we have `foo|while true; (( x++ )); done', and hit
 		 * ^C, we have to stop the loop, too. */
 		if ((val & 0200) && inforeground == 1) {
+		    if (!errbrk_saved) {
+			errbrk_saved = 1;
+			prev_breaks = breaks;
+			prev_errflag = errflag;
+		    }
 		    breaks = loops;
 		    errflag = 1;
 		    inerrflush();
@@ -322,6 +333,11 @@ update_job(Job jn)
 	    }
 	}
     } else if (list_pipe && (val & 0200) && inforeground == 1) {
+	if (!errbrk_saved) {
+	    errbrk_saved = 1;
+	    prev_breaks = breaks;
+	    prev_errflag = errflag;
+	}
 	breaks = loops;
 	errflag = 1;
 	inerrflush();
@@ -1296,6 +1312,7 @@ bin_fg(char *name, char **argv, char *ops, int func)
 		    thisjob = job;
 		    if ((jobtab[job].stat & STAT_SUPERJOB) &&
 			((!jobtab[job].procs->next ||
+			  (jobtab[job].stat & STAT_SUBLEADER) ||
 			  killpg(jobtab[job].gleader, 0) == -1)) &&
 			jobtab[jobtab[job].other].gleader)
 			attachtty(jobtab[jobtab[job].other].gleader);
diff --git a/Src/zsh.h b/Src/zsh.h
index 4be365901..3ad91b922 100644
--- a/Src/zsh.h
+++ b/Src/zsh.h
@@ -636,6 +636,7 @@ struct job {
 #define STAT_NOSTTY	(1<<11)	/* the tty settings are not inherited   */
 				/* from this job when it exits.         */
 #define STAT_ATTACH	(1<<12)	/* delay reattaching shell to tty       */
+#define STAT_SUBLEADER  (1<<13) /* is super-job, but leader is sub-shell */
 
 #define SP_RUNNING -1		/* fake status for jobs currently running */