On 4/11/19 6:03 PM, Daniel Kahn Gillmor wrote: >>>>> https://bugs.debian.org/920455 >>>> >>>> It wouldn't really affect that. The reason `wait' waits for process >>>> substitution processes is that they set $!, making them "known to the >>>> shell" and subject to wait without arguments. >>>> >>>> http://pubs.opengroup.org/onlinepubs/9699919799/utilities/wait.html#tag_20_153 >>> >>> This behavior is actually different between bash 4.4.18 and 5.0, but i >>> think this is a separate discussion, so i'll defer it to a different >>> thread to avoid confusion here :) >> >> Yes. It was reported as a bug against bash-4.3, back in 2015, and I agreed >> with it, so the behavior changed. >> >> http://lists.gnu.org/archive/html/bug-bash/2015-03/msg00076.html > > I understand why you made the change, i think. I'm just observing that > the change that was made has an observable impact on any child process > that happens to be bash. > > here's bash 5.0 taking 3 seconds to run a command that posh and zsh and > dash all run in 0 seconds: > > $ for x in posh dash zsh bash; do printf 'shell: %s\n' "$x"; time -p dash -c > "exec $x -c wait" 2> >(sleep 3); done > shell: posh > real 0.03 > user 0.00 > sys 0.00 > shell: dash > real 0.00 > user 0.00 > sys 0.00 > shell: zsh > real 0.00 > user 0.00 > sys 0.00 > shell: bash > real 3.00 > user 0.00 > sys 0.00 > $ > > Note that the subshell does no process subsitution whatsoever -- the > process substitution is all happening in the outer loop.
But the execs mean that the shell that is eventually invoked to run the `wait' is the parent of the process substitution. So the subshell has children, whether or not it has run the process substitution itself. Then the question becomes whether wait without arguments should wait for all children of the shell, or whether it should only wait for those children it knows it has started. I can change the code to wait for just the process substitution processes the current shell has started and "are known to the invoking shell". The difference between this code and bash-4.4 is that bash-4.4, of course, didn't try to wait for process substitution processes at all, and didn't care about children that weren't attached to a job (e.g., coprocs). (That in itself generated some complaints.) > Why are the process substitutions children of the spawned process and > not children of the parent bash shell itself? When running a command that is not a builtin or shell function, redirections happen in the child process. So in the above loop, the process substitution (which is the `word' attached to the output redirection), happens in a child of the shell running the loop. The `time' doesn't affect this at all -- it's a command modifier, not an actual builtin. The parent shell forks to run dash, and that process (say it's pid 1234) executes the process substitution, performs the output redirection, and execs dash. Dash (process 1234) looks at its arguments, finds -c, and execs `bash -c wait'. The bash (process 1234) executes wait without arguments, and waits for all of its children. > As someone who writes bash > scripts that use the wait builtin, it's a little distressing to me that > their behavior changes based on whether they are exec()ed in a process > that already has children or not. Should wait without arguments wait for all children of the current shell process? Or should it allow them to become orphaned? -- ``The lyf so short, the craft so long to lerne.'' - Chaucer ``Ars longa, vita brevis'' - Hippocrates Chet Ramey, UTech, CWRU c...@case.edu http://tiswww.cwru.edu/~chet/
signature.asc
Description: OpenPGP digital signature