diff --git a/NEWS b/NEWS index e261d1d0e..c86d3b8a6 100644 --- a/NEWS +++ b/NEWS @@ -8,6 +8,12 @@ Any uppercase BUG_* names are modernish shell bug IDs. - Fixed: 'typeset -xu' and 'typeset -xl' (export + change case) failed to change the case of a variable's value in certain conditions. +- A ksh 93u+ regression was fixed in the combination of ERR trap handling and + the 'pipefail' option. A pipeline now triggers the ERR trap correctly again + if the 'pipefail' option is active and any of the pipeline elements return a + nonzero exit status. Similarly, if both the 'errexit' and 'pipefail' options + are active, ksh now correctly exits if any pipeline element returns nonzero. + 2020-09-28: - While executing a ksh-style function, ksh 93u+ ignored all signals for which diff --git a/src/cmd/ksh93/sh/xec.c b/src/cmd/ksh93/sh/xec.c index a1aa3259c..da6a66a6a 100644 --- a/src/cmd/ksh93/sh/xec.c +++ b/src/cmd/ksh93/sh/xec.c @@ -1819,7 +1819,7 @@ int sh_exec(register const Shnode_t *t, int flags) type = shp->exitval; if(!(type&SH_EXITSIG)) { - /* wait for remainder of pipline */ + /* wait for remainder of pipeline */ if(shp->pipepid>1) { job_wait(shp->pipepid); @@ -1834,11 +1834,6 @@ int sh_exec(register const Shnode_t *t, int flags) sh_iounpipe(shp); shp->pipepid = 0; shp->st.ioset = 0; - if(simple && was_errexit) - { - echeck = 1; - sh_onstate(SH_ERREXIT); - } } if(jmpval>SH_JMPIO) siglongjmp(*shp->jmplist,jmpval); @@ -1908,6 +1903,7 @@ int sh_exec(register const Shnode_t *t, int flags) int savejobid = job.curjobid; int *exitval=0,*saveexitval = job.exitval; pid_t savepgid = job.curpgid; + echeck = 1; job.exitval = 0; job.curjobid = 0; if(shp->subshell) diff --git a/src/cmd/ksh93/tests/basic.sh b/src/cmd/ksh93/tests/basic.sh index dd7029ff4..f3c99b314 100755 --- a/src/cmd/ksh93/tests/basic.sh +++ b/src/cmd/ksh93/tests/basic.sh @@ -523,9 +523,11 @@ do print hello done | "$binsleep" .1 (( (SECONDS-s) < .2 )) || err_exit 'early termination not causing broken pipe' -[[ $({ trap 'print trap' 0; print -n | $(whence -p cat); } & wait $!) == trap ]] || err_exit 'trap on exit not getting triggered' -var=$({ trap 'print trap' ERR; print -n | $binfalse; } & wait $!) -[[ $var == trap ]] || err_exit 'trap on ERR not getting triggered' +got=$({ trap 'print trap' 0; print -n | "$bincat"; } & wait "$!") +[[ $got == trap ]] || err_exit "trap on exit not correctly triggered (expected 'trap', got $(printf %q "$got"))" + +got=$({ trap 'print trap' ERR; print -n | "$binfalse"; } & wait "$!") +[[ $got == trap ]] || err_exit "trap on ERR not correctly triggered (expected 'trap', got $(printf %q "$got"))" exp= got=$( diff --git a/src/cmd/ksh93/tests/options.sh b/src/cmd/ksh93/tests/options.sh index b0bc12879..8232db31a 100755 --- a/src/cmd/ksh93/tests/options.sh +++ b/src/cmd/ksh93/tests/options.sh @@ -561,5 +561,15 @@ actual=$(set +B; echo ${ echo test{1,2}; }) [[ $actual == "$expect" ]] || err_exit 'Brace expansion not turned off in ${ comsub; }' \ "(expected $(printf %q "$expect"), got $(printf %q "$actual"))" +# ====== +# ksh 93u+ did not correctly handle the combination of pipefail and (errexit or the ERR trap). +# https://github.com/ksh93/ksh/issues/121 +got=$("$SHELL" -o errexit -o pipefail -c '(exit 3) | true; echo "still here despite $? status"' 2>&1) +let "(e=$?)==3" && [[ -z $got ]] || err_exit 'errexit + pipefail failed' \ + "(expected status 3, ''; got status $e, $(printf %q "$got"))" +got=$("$SHELL" -o pipefail -c 'trap "print ERR\ trap" ERR; true | exit 3 | false | true | true' 2>&1) +let "(e=$?)==1" && [[ $got == 'ERR trap' ]] || err_exit 'ERR trap + pipefail failed' \ + "(expected status 1, 'ERR trap'; got status $e, $(printf %q "$got"))" + # ====== exit $((Errors<125?Errors:125))