diff options
-rw-r--r-- | ChangeLog | 8 | ||||
-rw-r--r-- | Src/jobs.c | 52 | ||||
-rw-r--r-- | Test/A05execution.ztst | 11 |
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. |