diff --git a/NEWS b/NEWS index 9cf77c610..5a04ba336 100644 --- a/NEWS +++ b/NEWS @@ -3,6 +3,15 @@ For full details, see the git log at: https://github.com/ksh93/ksh Any uppercase BUG_* names are modernish shell bug IDs. +2020-09-28: + +- While executing a ksh-style function, ksh 93u+ ignored all signals for which + the function had not set a local trap, except for SIGINT and SIGQUIT. This + was contrary to the manual, which states that a "trap condition that is not + caught or ignored by the function causes the function to terminate and the + condition to be passed on to the caller". This has now been fixed in 93u+m to + match the documentation, so that e.g. global traps work as expected again. + 2020-09-27: - The shell's lexical analysis of a 'case' statement within a do...done block diff --git a/src/cmd/ksh93/include/version.h b/src/cmd/ksh93/include/version.h index b80398542..901a973f4 100644 --- a/src/cmd/ksh93/include/version.h +++ b/src/cmd/ksh93/include/version.h @@ -17,4 +17,4 @@ * David Korn * * * ***********************************************************************/ -#define SH_RELEASE "93u+m 2020-09-27" +#define SH_RELEASE "93u+m 2020-09-28" diff --git a/src/cmd/ksh93/sh/xec.c b/src/cmd/ksh93/sh/xec.c index 7abafe4b5..b0fbca6b1 100644 --- a/src/cmd/ksh93/sh/xec.c +++ b/src/cmd/ksh93/sh/xec.c @@ -3193,7 +3193,7 @@ int sh_funscope(int argn, char *argv[],int(*fun)(void*),void *arg,int execflg) } if(jmpval) r=shp->exitval; - if(r>SH_EXITSIG && ((r&SH_EXITMASK)==SIGINT || ((r&SH_EXITMASK)==SIGQUIT))) + if(nsig && r>SH_EXITSIG) kill(shgd->current_pid,r&SH_EXITMASK); if(jmpval > SH_JMPFUN) { diff --git a/src/cmd/ksh93/tests/signal.sh b/src/cmd/ksh93/tests/signal.sh index c69e798ab..e927081b8 100755 --- a/src/cmd/ksh93/tests/signal.sh +++ b/src/cmd/ksh93/tests/signal.sh @@ -426,6 +426,8 @@ then { [[ $(kill -l $?) == RTMIN ]] || err_exit 'wait interrupted by signal not caught should exit with the value of that signal+256' fi +# sh.1: "A trap condition that is not caught or ignored by the function causes +# the function to terminate and the condition to be passed on to the caller." function b { sleep .3 @@ -434,16 +436,17 @@ function b function a { - trap 'print int' TERM + trap 'endc=1' TERM b enda=1 } { sleep .1;kill -s TERM $$;}& -unset enda endb +unset enda endb endc a [[ $endb ]] && err_exit 'TERM signal did not kill function b' [[ $enda == 1 ]] || err_exit 'TERM signal killed function a' +[[ $endc == 1 ]] || err_exit 'TERM trap not triggered in function a' # ====== # Exit status checks @@ -494,5 +497,35 @@ got=$(export sig; "$SHELL" -c ' ((!(e = $?))) && [[ $got == "$exp" ]] || err_exit "failed to handle SIG$sig from subshell" \ "(got status $e$( ((e>128)) && print -n / && kill -l "$e"), $(printf %q "$got"))" +got=$(export sig; "$SHELL" -c ' + function tryTrap + { + kill -s "$1" "$$" + } + trap "print '\''OK: $sig'\''" "$sig" + tryTrap "$sig" + trap - "$sig" +' 2>&1) +((!(e = $?))) && [[ $got == "$exp" ]] || err_exit "failed to handle SIG$sig from ksh function" \ + "(got status $e$( ((e>128)) && print -n / && kill -l "$e"), $(printf %q "$got"))" + +# ====== +# ksh-style functions didn't handle signals other than SIGINT and SIGQUIT (rhbz#1454804) +exp="HUP INT PIPE QUIT TERM USR1 USR2" +got=$(export exp; "$SHELL" -c ' + function tryTrap + { + kill -s "$1" "$$" + } + for sig in $exp # split + do trap "print -n '\''$sig '\''" "$sig" + tryTrap "$sig" + trap - "$sig" + done +' 2>&1) +got=${got% } # rm final space +((!(e = $?))) && [[ $got == "$exp" ]] || err_exit "ksh function ignores global signal traps" \ + "(got status $e$( ((e>128)) && print -n / && kill -l "$e"), $(printf %q "$got"))" + # ====== exit $((Errors<125?Errors:125))