From 400806afa6bd361a66077430401e85e146034fa4 Mon Sep 17 00:00:00 2001 From: Martijn Dekker Date: Sun, 3 Jul 2022 00:54:01 +0200 Subject: [PATCH] Do not avoid creating subshell for last command if there are traps Reproducer: $ ksh -c 'trap "echo OK" TERM; (kill -s TERM $$)' Actual output: none Expected output: OK The bug is only triggered if 'kill' is executed from a subshell that is optimised out due to being the last command in the script. src/cmd/ksh93/sh/xec.c: sh_exec(): case TPAR: - Instead of only checking for EXIT and ERR traps, do not avoid creating a virtual subshell if there are any traps (except DEBUG, SIGKILL, SIGSTOP); for this, use the sh.st.trapdontexec flag introduced in 40245e08. --- NEWS | 3 +++ src/cmd/ksh93/sh/xec.c | 2 +- src/cmd/ksh93/tests/subshell.sh | 6 ++++++ 3 files changed, 10 insertions(+), 1 deletion(-) diff --git a/NEWS b/NEWS index 82f453eb4..a82d7e879 100644 --- a/NEWS +++ b/NEWS @@ -9,6 +9,9 @@ Any uppercase BUG_* names are modernish shell bug IDs. command that was terminated by a signal, the exit status ($?) of the subshell did not reflect this by adding 256 to the signal number. +- Fixed a bug that caused signal traps to be ignored if the shell was + signalled from a subshell that is the last command in the script. + 2022-07-01: - In scripts, $COLUMNS and $LINES are now kept up to date in scripts at diff --git a/src/cmd/ksh93/sh/xec.c b/src/cmd/ksh93/sh/xec.c index 910fcdcc5..9baf6efe7 100644 --- a/src/cmd/ksh93/sh/xec.c +++ b/src/cmd/ksh93/sh/xec.c @@ -1830,7 +1830,7 @@ int sh_exec(register const Shnode_t *t, int flags) case TPAR: echeck = 1; flags &= ~OPTIMIZE_FLAG; - if(!sh.subshell && !sh.st.trapcom[0] && !sh.st.trap[SH_ERRTRAP] && (flags&sh_state(SH_NOFORK))) + if(!sh.subshell && !sh.st.trapdontexec && (flags&sh_state(SH_NOFORK))) { /* This is the last command, so avoid creating a subshell */ char *savsig; diff --git a/src/cmd/ksh93/tests/subshell.sh b/src/cmd/ksh93/tests/subshell.sh index 43f461aff..c90feecfe 100755 --- a/src/cmd/ksh93/tests/subshell.sh +++ b/src/cmd/ksh93/tests/subshell.sh @@ -1171,5 +1171,11 @@ let "(got=$?)==(exp&0xFF)" || err_exit "fake signal exit from virtual subshell: (ulimit -t unlimited 2>/dev/null; exit "$exp") let "(got=$?)==(exp&0xFF)" || err_exit "fake signal exit from real subshell: expected status $((exp&0xFF)), got status $got" +# ====== +got=$(set +x; { "$SHELL" -c 'trap "echo OK" TERM; (kill -s TERM $$)'; } 2>&1) +exp=OK +[[ $got == "$exp" ]] || err_exit 'trap ignored when signalled from a subshell that is the last command' \ + "(expected $(printf %q "$exp"), got $(printf %q "$got"))" + # ====== exit $((Errors<125?Errors:125))