From c3114a7735c85b79771e08bd156470bde1a36950 Mon Sep 17 00:00:00 2001 From: "Barton E. Schaefer" Date: Sat, 26 Oct 2013 16:11:40 -0700 Subject: 31906: fix race-condition interaction of $pipestatus with job control printjob() should not reference oldjobtab for job numbers unless it is being called from bin_fg(). printjob() also must not attempt to update pipestats when called from bin_fg(). acquire_pgrp() should not loop infintely if the shell is not interactive. Update the $pipestatus stress test so that it also exercises the oldjobtab repair. --- ChangeLog | 11 +++++++++++ Src/jobs.c | 13 ++++++++++--- Test/A05execution.ztst | 10 ++++++++-- 3 files changed, 29 insertions(+), 5 deletions(-) diff --git a/ChangeLog b/ChangeLog index 0561a3e0c..8601ba508 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,14 @@ +2013-10-26 Barton E. Schaefer + + * 31906: Src/jobs.c, Test/A05execution.ztst: printjob() should not + reference oldjobtab for job numbers unless it is being called from + bin_fg(). Add a DPUTS check in case this goes horribly wrong. + printjob() also must not attempt to update pipestats when called + from bin_fg(). Finally, acquire_pgrp() cannot acquire the tty + group leader if the shell is not interactive, so avoid looping + infinitely in the attempt. Update the $pipestatus stress test so + that it also exercises the oldjobtab repair. + 2013-10-25 Peter Stephenson * 31890 (with Mikael's fixes in 31891): NEWS: add descriptions diff --git a/Src/jobs.c b/Src/jobs.c index c218743f0..336c5d4cf 100644 --- a/Src/jobs.c +++ b/Src/jobs.c @@ -941,10 +941,13 @@ printjob(Job jn, int lng, int synch) int doneprint = 0, skip_print = 0; FILE *fout = (synch == 2 || !shout) ? stdout : shout; - if (oldjobtab != NULL) + if (synch > 1 && oldjobtab != NULL) job = jn - oldjobtab; else job = jn - jobtab; + DPUTS3(job < 0 || job > (synch > 1 ? oldmaxjob : maxjob), + "bogus job number, jn = %L, jobtab = %L, oldjobtab = %L", + (long)jn, (long)jobtab, (long)oldjobtab); if (jn->stat & STAT_NOPRINT) { skip_print = 1; @@ -995,7 +998,8 @@ printjob(Job jn, int lng, int synch) if (skip_print) { if (jn->stat & STAT_DONE) { /* This looks silly, but see update_job() */ - storepipestats(jn, job == thisjob, job == thisjob); + if (synch <= 1) + storepipestats(jn, job == thisjob, job == thisjob); if (should_report_time(jn)) dumptime(jn); deletejob(jn, 0); @@ -1128,7 +1132,8 @@ printjob(Job jn, int lng, int synch) if (jn->stat & STAT_DONE) { /* This looks silly, but see update_job() */ - storepipestats(jn, job == thisjob, job == thisjob); + if (synch <= 1) + storepipestats(jn, job == thisjob, job == thisjob); if (should_report_time(jn)) dumptime(jn); deletejob(jn, 0); @@ -2610,6 +2615,8 @@ acquire_pgrp(void) while ((ttpgrp = gettygrp()) != -1 && ttpgrp != mypgrp) { mypgrp = GETPGRP(); if (mypgrp == mypid) { + if (!interact) + break; /* attachtty() will be a no-op, give up */ signal_setmask(oldset); attachtty(mypgrp); /* Might generate SIGT* */ signal_block(blockset); diff --git a/Test/A05execution.ztst b/Test/A05execution.ztst index 8578016ab..ba7e02cd5 100644 --- a/Test/A05execution.ztst +++ b/Test/A05execution.ztst @@ -179,17 +179,23 @@ 0:Status reset by starting a backgrounded command >0 - repeat 2048; do (: | : | while false; do + setopt MONITOR + [[ -o MONITOR ]] || print -u $ZTST_fd 'Unable to change MONITOR option' + repeat 2048; do (return 2 | + return 1 | + while true; do + false break done; print "${pipestatus[@]}") ZTST_hashmark done | sort | uniq -c | sed 's/^ *//' 0:Check whether `$pipestatus[]' behaves. ->2048 0 0 0 +>2048 2 1 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. + setopt MONITOR externFunc() { awk >/dev/null 2>&1; true; } false | true | false | true | externFunc echo $pipestatus -- cgit 1.4.1