Skip to content

Commit

Permalink
Allow exec of last command in forked non-bg subshell (re: 2124f14)
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
McDutchie committed Jun 18, 2022
1 parent 2124f14 commit f0b0b67
Show file tree
Hide file tree
Showing 3 changed files with 15 additions and 2 deletions.
1 change: 0 additions & 1 deletion src/cmd/ksh93/sh/subshell.c
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand Down
6 changes: 5 additions & 1 deletion src/cmd/ksh93/sh/xec.c
Original file line number Diff line number Diff line change
Expand Up @@ -1999,7 +1999,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;
}

Expand Down
10 changes: 10 additions & 0 deletions src/cmd/ksh93/tests/basic.sh
Original file line number Diff line number Diff line change
Expand Up @@ -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; } <out && let "pid1 == pid2" \
|| err_exit "last command in forked subshell not exec-optimized ($pid1 != $pid2)"
# ======
exit $((Errors<125?Errors:125))

0 comments on commit f0b0b67

Please sign in to comment.