diff options
author | Ron Yorston <rmy@pobox.com> | 2021-08-30 20:31:42 +0100 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2021-09-30 00:15:33 +0200 |
commit | 76ef4391548ded8db511e2f7f8f35a3010be7ec5 (patch) | |
tree | 0bb58db5de47e8fc3b9a265b9b1206a054b443c4 | |
parent | 00adcdb64a5487f0ea6b400d912dcf7c58637696 (diff) | |
download | busybox-w32-76ef4391548ded8db511e2f7f8f35a3010be7ec5.tar.gz busybox-w32-76ef4391548ded8db511e2f7f8f35a3010be7ec5.tar.bz2 busybox-w32-76ef4391548ded8db511e2f7f8f35a3010be7ec5.zip |
ash: regressions in process substitution
Stacy Harper reports that this script:
test() { . /tmp/bb_test; }
echo "export TEST=foo" >/tmp/bb_test
test 2>/dev/null
echo "$TEST"
correctly prints 'foo' in BusyBox 1.33 but hangs in 1.34.
Bisection suggested the problem was caused by commit a1b0d3856 (ash: add
process substitution in bash-compatibility mode). Removing the call to
unwindredir() in cmdloop() introduced in that commit makes the script
work again.
Additionally, these examples of process substitution:
while true; do cat <(echo hi); done
f() { while true; do cat <(echo hi); done }
f
result in running out of file descriptors. This is a regression from
v5 of the process substitution patch caused by changes to evalcommand()
not being transferred to v6.
function old new delta
static.pushredir - 99 +99
evalcommand 1729 1750 +21
exitreset 69 86 +17
cmdloop 372 365 -7
unwindredir 28 - -28
pushredir 112 - -112
------------------------------------------------------------------------------
(add/remove: 1/2 grow/shrink: 2/1 up/down: 137/-147) Total: -10 bytes
Signed-off-by: Ron Yorston <rmy@pobox.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r-- | shell/ash.c | 10 |
1 files changed, 7 insertions, 3 deletions
diff --git a/shell/ash.c b/shell/ash.c index b5947147a..53c140930 100644 --- a/shell/ash.c +++ b/shell/ash.c | |||
@@ -10278,6 +10278,9 @@ evalcommand(union node *cmd, int flags) | |||
10278 | 10278 | ||
10279 | /* First expand the arguments. */ | 10279 | /* First expand the arguments. */ |
10280 | TRACE(("evalcommand(0x%lx, %d) called\n", (long)cmd, flags)); | 10280 | TRACE(("evalcommand(0x%lx, %d) called\n", (long)cmd, flags)); |
10281 | #if BASH_PROCESS_SUBST | ||
10282 | redir_stop = redirlist; | ||
10283 | #endif | ||
10281 | file_stop = g_parsefile; | 10284 | file_stop = g_parsefile; |
10282 | back_exitstatus = 0; | 10285 | back_exitstatus = 0; |
10283 | 10286 | ||
@@ -10356,7 +10359,11 @@ evalcommand(union node *cmd, int flags) | |||
10356 | lastarg = nargv[-1]; | 10359 | lastarg = nargv[-1]; |
10357 | 10360 | ||
10358 | expredir(cmd->ncmd.redirect); | 10361 | expredir(cmd->ncmd.redirect); |
10362 | #if !BASH_PROCESS_SUBST | ||
10359 | redir_stop = pushredir(cmd->ncmd.redirect); | 10363 | redir_stop = pushredir(cmd->ncmd.redirect); |
10364 | #else | ||
10365 | pushredir(cmd->ncmd.redirect); | ||
10366 | #endif | ||
10360 | preverrout_fd = 2; | 10367 | preverrout_fd = 2; |
10361 | if (BASH_XTRACEFD && xflag) { | 10368 | if (BASH_XTRACEFD && xflag) { |
10362 | /* NB: bash closes fd == $BASH_XTRACEFD when it is changed. | 10369 | /* NB: bash closes fd == $BASH_XTRACEFD when it is changed. |
@@ -13477,9 +13484,6 @@ cmdloop(int top) | |||
13477 | if (doing_jobctl) | 13484 | if (doing_jobctl) |
13478 | showjobs(SHOW_CHANGED|SHOW_STDERR); | 13485 | showjobs(SHOW_CHANGED|SHOW_STDERR); |
13479 | #endif | 13486 | #endif |
13480 | #if BASH_PROCESS_SUBST | ||
13481 | unwindredir(NULL); | ||
13482 | #endif | ||
13483 | inter = 0; | 13487 | inter = 0; |
13484 | if (iflag && top) { | 13488 | if (iflag && top) { |
13485 | inter++; | 13489 | inter++; |