bug-bash
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: wait inside subshell waits for sibling


From: Emanuele Torre
Subject: Re: wait inside subshell waits for sibling
Date: Mon, 24 Oct 2022 10:52:22 +0200

On 24/10/2022, Robert Elz <kre@munnari.oz.au> wrote:
> It need not make a difference.   The wait command is not intended to
> be just the wait(2) (or wait(3) whichever it is on the system in
> question) system call (or wrapper around another system call).

I don't see how this is relevant.

> There's no reason that wait (the command) cannot check for candidate
> jobs which are still running, and wait for any of those, and then
> return as soon as there are none left.   That the shell happens to
> have forked other processes for its own reasons should make no
> difference at all.

Process substitutions are considered background jobs, and the wait
builtin waits for them.

    bash-5.1$ printf '%()T\n'; exec {fd}> >(sleep 3); wait; printf '%()T\n'
    10:22:19
    10:22:22

> That is an entirely different issue, and is working as is supposed
> to work.   That it isn't what some people might expect is irrelevant.

What do you mean? The problem that was described is caused by that
optimisation (not the version that is applied to simple commands that
run external program, but to subshell compound command as mentioned).

In case you did not understand, the issue is not that "wait inside
subshell waits for sibling", because the process that runs `cat' IS NOT
a sibling of the process that runs `wait', it is a CHILD.

bash will always evalute  (CMDS) REDIRS  as  (exec REDIRS; CMDS).

To show that this optimisation also affects subshell compound commands,
and not just simple commands that run external programs, here is an
example script that breaks just like the previous example (i.e. loops
infinitely and keeps running `echo hi > /tmp/file1'), and does so even
thought `echo' is a shell builtin:

    i=0
    while [ "$i" -lt 10 ]; do
      (echo hi) > "/tmp/file$(( ++i ))"
      sleep 1
    done

In this case,  (: & wait) > >(cat)  is run as (exec > >(cat); : & wait).
Since it is that subshell that evaluates `> >(cat)', and not the shell
that runs the subshell compound command, `cat' is a background job of
the subshell, and wait, in the subshell, will wait for it.

(CMDS) REDIRS  =>  (exec REDIRS; CMDS)  is arguably an incorrect
optimisation (afaik, only bash peforms it; ksh93 performs the simple
command optimisation, but not this one), but that is what is causing the
issue, and, as i previously noted, bash has been performing this
optimisation (just like the simple command version) for a while.

This is not a problem with the `wait' builtin waiting for a sibling
since `cat' is not its sibling; and this is not a problem caused by
`wait' incorrectly waiting for process substitution processes (`wait'
should wait for those!).

emanuele6



reply via email to

[Prev in Thread] Current Thread [Next in Thread]