summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog8
-rw-r--r--Src/jobs.c52
-rw-r--r--Test/A05execution.ztst11
3 files changed, 54 insertions, 17 deletions
diff --git a/ChangeLog b/ChangeLog
index e882c762e..6eb21a194 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,11 @@
+2013-10-23 Barton E. Schaefer <schaefer@zsh.org>
+
+ * 31879: Src/jobs.c: improve $pipestatus behavior when the last
+ command in the pipeline is executed within the current shell
+
+ * unposted (cf. Frank Terbeck: 30047): Test/A05redirect.ztst:
+ stress test for $pipestatus handling
+
2013-10-23 Peter Stephenson <p.stephenson@samsung.com>
* 31873: Doc/Zsh/builtins.yo: Document conventions for use of
diff --git a/Src/jobs.c b/Src/jobs.c
index b9d7a84cc..82ffdf21a 100644
--- a/Src/jobs.c
+++ b/Src/jobs.c
@@ -376,6 +376,30 @@ check_cursh_sig(int sig)
}
}
+/**/
+int
+storepipestats(Job jn, int inforeground)
+{
+ int i, pipefail = 0, jpipestats[MAX_PIPESTATS];
+ Process p;
+
+ for (p = jn->procs, i = 0; p && i < MAX_PIPESTATS; p = p->next, i++) {
+ jpipestats[i] = ((WIFSIGNALED(p->status)) ?
+ 0200 | WTERMSIG(p->status) :
+ WEXITSTATUS(p->status));
+ if (jpipestats[i])
+ pipefail = jpipestats[i];
+ }
+ if (inforeground) {
+ memcpy(pipestats, jpipestats, sizeof(int)*i);
+ if ((jn->stat & STAT_CURSH) && i < MAX_PIPESTATS)
+ pipestats[i++] = lastval;
+ numpipestats = i;
+ }
+
+ return pipefail;
+}
+
/* Update status of job, possibly printing it */
/**/
@@ -507,24 +531,16 @@ update_job(Job jn)
return;
jn->stat |= (somestopped) ? STAT_CHANGED | STAT_STOPPED :
STAT_CHANGED | STAT_DONE;
- if (job == thisjob && (jn->stat & STAT_DONE)) {
- int i, newlastval = 0;
- Process p;
-
- for (p = jn->procs, i = 0; p && i < MAX_PIPESTATS; p = p->next, i++) {
- pipestats[i] = ((WIFSIGNALED(p->status)) ?
- 0200 | WTERMSIG(p->status) :
- WEXITSTATUS(p->status));
- if (pipestats[i])
- newlastval = pipestats[i];
- }
- if ((jn->stat & STAT_CURSH) && i < MAX_PIPESTATS) {
- pipestats[i++] = lastval;
- if (!lastval && isset(PIPEFAIL))
+ 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;
- } else if (isset(PIPEFAIL))
- lastval= newlastval;
- numpipestats = i;
+ }
}
if (!inforeground &&
(jn->stat & (STAT_SUBJOB | STAT_DONE)) == (STAT_SUBJOB | STAT_DONE)) {
@@ -975,6 +991,7 @@ printjob(Job jn, int lng, int synch)
if (skip_print) {
if (jn->stat & STAT_DONE) {
+ (void) storepipestats(jn, job == thisjob);
if (should_report_time(jn))
dumptime(jn);
deletejob(jn, 0);
@@ -1105,6 +1122,7 @@ printjob(Job jn, int lng, int synch)
/* delete job if done */
if (jn->stat & STAT_DONE) {
+ (void) storepipestats(jn, job == thisjob);
if (should_report_time(jn))
dumptime(jn);
deletejob(jn, 0);
diff --git a/Test/A05execution.ztst b/Test/A05execution.ztst
index b4fb8739a..c42e454f3 100644
--- a/Test/A05execution.ztst
+++ b/Test/A05execution.ztst
@@ -178,3 +178,14 @@
kill $!
0:Status reset by starting a backgrounded command
>0
+
+ repeat 2048; do (: | : | while false; do
+ break
+ done;
+ print "${pipestatus[@]}")
+ ZTST_hashmark
+ done | sort | uniq -c
+0:Check whether `$pipestatus[]' behaves.
+> 2048 0 0 0
+F:This test checks for a bug in `$pipestatus[]' handling. If it breaks then
+F:the bug is still there or it reappeared. See workers-29973 for details.