In the current devel branch, even if we close all standard streams of
a background process started in `eval' in a command substitution, the
command substitution blocks until the background process terminates.

The following is a reduced test case:

$ ./bash -c 'pid=$(eval "sleep 3" < /dev/null &> /dev/null & echo "$!")'

In all the older Bash versions, the above command exits immediately
after receiving the contents of $!. However, in Bash on the devel
branch, the above command waits for the termination of the background
process. The issue doesn't happen without "eval".

The behavior change was introduced in commit 044c1ac with the
following change log:

>                    2/15
>                    ----
> execute_cmd.c
>     - execute_subshell_builtin_or_function: after executing the command(s)
>       and before running the EXIT trap, undo any redirections from the
>       last command so the exit trap runs in an environment without those
>       redirections. This makes builtins run in a subshell more like those
>       run in the shell's execution environment

Bash started to preserve the original stdout (connected to the pipe of
the command substitution) for the undo redirections for a possible
execution of the EXIT trap, even if the user tries to close the file
descriptor of the background process by redirecting it to /dev/null.

The present behavior isn't consistent with older Bash versions. Also,
the above use of command substitution is typical. Although the
specific use of `eval' in this pattern may not be typical, I hit this
through a utility that receives an arbitrary string as a command and
starts it as a background process.

Couldn't the behavior be adjusted? For example, when the EXIT trap is
not set (or is inactive in the current subshell), we do not have to
preserve the original file descriptors for those undo redirections.

--
Koichi

Reply via email to