1
0
Fork 0
mirror of git://git.code.sf.net/p/cdesktopenv/code synced 2025-03-09 15:50:02 +00:00

Fork before entering shared-state command substitution

The code contains various checks to see if a subshell needs to
fork, like this one in the ulimit builtin:

	if(shp->subshell && !shp->subshare)
		sh_subfork();

All checks of this form are fatally broken, as each one of them
causes shared-state command substitutions to ignore parent virtual
subshells.

Currently the only feasible way to fix this is to fork a virtual
subshell before executing a shared-state command substitution in
it. In the long term I think shared-state command substitutions
should probably be redesigned to disassociate them completely from
the virtual subshell mechanism.

src/cmd/ksh93/sh/macro.c: comsubst():
- If we're in a non-subshare virtual subshell, fork it before
  entering a type 2 (subshare) command substitution.

src/cmd/ksh93/sh/subshell.c:
- sh_assignok(): Remove subshare fix from 911d6b06 as it's
  redundant now that the parent of a subshare is never a virtual
  subshell. Go back to not doing anything if the current "subshell"
  is a subshare.
- sh_subtracktree(), sh_subfuntree(): Similarly, remove the
  now-redundant subshare fixes from 13c57e4b.

src/cmd/ksh93/sh/xec.c: sh_exec():
- Fix a separate bug: only fork a virtual subshell before running a
  background job if that "subshell" is not a subshare.

src/cmd/ksh93/tests/subshell.sh:
- Add test for bug fixed in xec.c.
- Add tests for 'ulimit', 'builtin' and 'exec' run in subshare
  within subshell -- all commands that use checks of the form
  'if(sh.subshell && !sh.subshare) sh_subfork();'.

Resolves: https://github.com/ksh93/ksh/issues/289
This commit is contained in:
Martijn Dekker 2021-05-01 00:47:39 +01:00
parent 72fe631b2f
commit 88a1f3d661
5 changed files with 29 additions and 38 deletions

View file

@ -1018,5 +1018,21 @@ dummy=${ : >&2; got='good'; }
[[ $got == "$exp" ]] || err_exit 'subshare stopped sharing state after command that redirects stdout' \
"(expected '$exp', got '$got')"
# ======
unset d x
exp='end 1'
got=$(d=${ true & x=1; echo end; }; echo $d $x)
[[ $got == "$exp" ]] || err_exit 'subshare forks when running background job' \
"(expected '$exp', got '$got')"
# ======
# https://github.com/ksh93/ksh/issues/289
got=$(ulimit -t unlimited 2>/dev/null; (dummy=${ ulimit -t 1; }); ulimit -t)
[[ $got == 1 ]] && err_exit "'ulimit' command run in subshare leaks out of parent virtual subshell"
got=$(_AST_FEATURES="TEST_TMP_VAR - $$" "$SHELL" -c '(d=${ builtin getconf;}); getconf TEST_TMP_VAR' 2>&1)
[[ $got == $$ ]] && err_exit "'builtin' command run in subshare leaks out of parent virtual subshell"
got=$(ulimit -t unlimited 2>/dev/null; (dummy=${ exec true; }); echo ok)
[[ $got == ok ]] || err_exit "'exec' command run in subshare disregards parent virtual subshell"
# ======
exit $((Errors<125?Errors:125))