summary refs log tree commit diff
diff options
context:
space:
mode:
authorBarton E. Schaefer <schaefer@zsh.org>2013-10-24 17:31:13 -0700
committerBarton E. Schaefer <schaefer@zsh.org>2013-10-24 17:31:13 -0700
commit5b30149638f45946c1a819010bd4d384dea76b5d (patch)
tree1d8f2f8d850edb774ddcbb11a676b94de6a28406
parent0c97990b207f2eb18e30fd2551a3f04ab678c368 (diff)
downloadzsh-5b30149638f45946c1a819010bd4d384dea76b5d.tar.gz
zsh-5b30149638f45946c1a819010bd4d384dea76b5d.tar.xz
zsh-5b30149638f45946c1a819010bd4d384dea76b5d.zip
31885: fix PIPEFAIL when the last command executes in the current shell
-rw-r--r--ChangeLog7
-rw-r--r--Src/jobs.c42
2 files changed, 30 insertions, 19 deletions
diff --git a/ChangeLog b/ChangeLog
index 8da6e3e1a..ae5af0d60 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -5,10 +5,15 @@
 	* 31877: Src/pattern.c: fix behaviour of disable -p for
 	entities with parentheses.
 
+2013-10-24  Barton E. Schaefer  <schaefer@zsh.org>
+
+	* 31885: Src/jobs.c: fix PIPEFAIL behavior when the last command
+	in a pipeline is executed within the current shell; add comments
+
 2013-10-24  Peter Stephenson  <p.stephenson@samsung.com>
 
 	* 31888: Test/A05execution.ztst: add test of pipestatus
-	that was reliable failing before 31879.
+	that was reliably failing before 31879.
 
 	* 31882: Src/Zle/compcore.c: better insulation of
 	completion widget excecution against job environment.
diff --git a/Src/jobs.c b/Src/jobs.c
index 82ffdf21a..c218743f0 100644
--- a/Src/jobs.c
+++ b/Src/jobs.c
@@ -377,8 +377,8 @@ check_cursh_sig(int sig)
 }
 
 /**/
-int
-storepipestats(Job jn, int inforeground)
+void
+storepipestats(Job jn, int inforeground, int fixlastval)
 {
     int i, pipefail = 0, jpipestats[MAX_PIPESTATS];
     Process p;
@@ -397,7 +397,13 @@ storepipestats(Job jn, int inforeground)
 	numpipestats = i;
     }
 
-    return pipefail;
+    if (fixlastval) {
+      if (jn->stat & STAT_CURSH) {
+	if (!lastval && isset(PIPEFAIL))
+	  lastval = pipefail;
+      } else if (isset(PIPEFAIL))
+	lastval = pipefail;
+    }
 }
 
 /* Update status of job, possibly printing it */
@@ -532,15 +538,12 @@ update_job(Job jn)
     jn->stat |= (somestopped) ? STAT_CHANGED | STAT_STOPPED :
 	STAT_CHANGED | STAT_DONE;
     if (jn->stat & STAT_DONE) {
-	int newlastval = storepipestats(jn, inforeground);
-
-	if (job == thisjob) {
-	    if (jn->stat & STAT_CURSH) {
-		if (!lastval && isset(PIPEFAIL))
-		    lastval = newlastval;
-	    } else if (isset(PIPEFAIL))
-		lastval = newlastval;
-	}
+	/* This may be redundant with printjob() but note that inforeground
+	 * is true here for STAT_CURSH jobs even when job != thisjob, most
+	 * likely because thisjob = -1 from exec.c:execsimple() trickery.
+	 * However, if we reset lastval here we break it for printjob().
+	 */
+	storepipestats(jn, inforeground, 0);
     }
     if (!inforeground &&
 	(jn->stat & (STAT_SUBJOB | STAT_DONE)) == (STAT_SUBJOB | STAT_DONE)) {
@@ -991,7 +994,8 @@ printjob(Job jn, int lng, int synch)
 
     if (skip_print) {
 	if (jn->stat & STAT_DONE) {
-	  (void) storepipestats(jn, job == thisjob);
+	    /* This looks silly, but see update_job() */
+	    storepipestats(jn, job == thisjob, job == thisjob);
 	    if (should_report_time(jn))
 		dumptime(jn);
 	    deletejob(jn, 0);
@@ -1107,9 +1111,9 @@ printjob(Job jn, int lng, int synch)
 	fflush(fout);
     }
 
-/* print "(pwd now: foo)" messages: with (lng & 4) we are printing
- * the directory where the job is running, otherwise the current directory
- */
+    /* print "(pwd now: foo)" messages: with (lng & 4) we are printing
+     * the directory where the job is running, otherwise the current directory
+     */
 
     if ((lng & 4) || (interact && job == thisjob &&
 		      jn->pwd && strcmp(jn->pwd, pwd))) {
@@ -1119,10 +1123,12 @@ printjob(Job jn, int lng, int synch)
 	fprintf(fout, ")\n");
 	fflush(fout);
     }
-/* delete job if done */
+
+    /* delete job if done */
 
     if (jn->stat & STAT_DONE) {
-	(void) storepipestats(jn, job == thisjob);
+	/* This looks silly, but see update_job() */
+	storepipestats(jn, job == thisjob, job == thisjob);
 	if (should_report_time(jn))
 	    dumptime(jn);
 	deletejob(jn, 0);