From d6c9821c5b20bc3cffc0b4447cc7086dc4de2ba5 Mon Sep 17 00:00:00 2001 From: Martijn Dekker Date: Sat, 18 Jun 2022 12:45:51 +0100 Subject: [PATCH] Allow exec of last command in forked non-bg subshell (re: 16b38021) The exec optimization only happened in background subshells and not in regular subshells when they had forked via sh_subfork(), which makes little sense. src/cmd/ksh93/sh/xec.c: sh_exec: case TLST: - A subshell is executed as a list of commands which is TLST. If the shell had not forked at the beginning of the subshell, the sh_state(SH_FORKED) flag was not passed on to recursive sh_exec() invocations, and a sh_subfork() event did not change this. To fix this, re-check for the SH_FORKED state and pass that bit on to the recursive sh_exec() invocation if set (note that sh_isstate() returns a bitmask and not a boolean value). src/cmd/ksh93/sh/subshell.c: sh_subfork(): - Remove redundant sh_onstate(SH_FORKED); this is already done in sh_fork() which this function calls. --- src/cmd/ksh93/sh/subshell.c | 1 - src/cmd/ksh93/sh/xec.c | 6 +++++- src/cmd/ksh93/tests/basic.sh | 10 ++++++++++ 3 files changed, 15 insertions(+), 2 deletions(-) diff --git a/src/cmd/ksh93/sh/subshell.c b/src/cmd/ksh93/sh/subshell.c index dd0e26d02..0b31429cd 100644 --- a/src/cmd/ksh93/sh/subshell.c +++ b/src/cmd/ksh93/sh/subshell.c @@ -187,7 +187,6 @@ void sh_subfork(void) else { /* this is the child part of the fork */ - sh_onstate(SH_FORKED); /* * $RANDOM is only reseeded when it's used in a subshell, so if $RANDOM hasn't * been reseeded yet set rp->rand_last to -2. This allows sh_save_rand_seed() diff --git a/src/cmd/ksh93/sh/xec.c b/src/cmd/ksh93/sh/xec.c index 65c3c805c..08f485985 100644 --- a/src/cmd/ksh93/sh/xec.c +++ b/src/cmd/ksh93/sh/xec.c @@ -1993,7 +1993,11 @@ int sh_exec(register const Shnode_t *t, int flags) t = t->lst.lstrit; } while(t->tre.tretyp == TLST); - sh_exec(t,flags); + /* + * if sh_state(SH_FORKED) was turned on in the meantime, mix it in to the flags to allow a last-command + * no_fork optimization via execflg2 -- this happens when a subshell forks mid-execution (sh_subfork()) + */ + sh_exec(t,flags|sh_isstate(SH_FORKED)); break; } diff --git a/src/cmd/ksh93/tests/basic.sh b/src/cmd/ksh93/tests/basic.sh index 7fc2207cf..31fb6336d 100755 --- a/src/cmd/ksh93/tests/basic.sh +++ b/src/cmd/ksh93/tests/basic.sh @@ -927,5 +927,15 @@ AIX | SunOS) ;; esac +# ====== +( + ulimit -t unlimited 2>/dev/null + print "${.sh.pid:-$("$SHELL" -c 'echo "$PPID"')}" # fallback for pre-93u+m ksh without ${.sh.pid} + "$SHELL" -c 'print "$$"' +) >out +pid1= pid2= +{ read pid1 && read pid2; }