On Tue, Jun 04, 2019 at 07:19:02PM -0400, Chet Ramey wrote: > On 6/4/19 4:34 PM, mwnx wrote: > > > Thanks for the explanation. In view of the change you describe, > > there is another behaviour that I think might qualify as a bug. I'll > > give you my actual use case first. > > > > I simply want to make sure all processes running inside a given > > subshell are killed on exit. To that means, I set up the following > > trap in the shell (and potentially, its subshells and so on): > > > > trap 'kill $(jobs -p) &>/dev/null || true; wait' EXIT > > > > This was working fine in bash 4.x, despite `jobs -p` not returning > > the process ID of process substitutions. But now that `wait` (with > > no arguments) waits for process substitutions in addition to > > "ordinary" foreground and background processes, the situation is > > asymmetric, leading to my subshells freezing when killed while a > > process substitution is running. > > Not quite. `wait' without arguments waits for the last process > substitution, and the pid of that process is available in $! for the > cases you care about. If you are sure that your script hasn't started > any asynchronous processes since the last process substitution, you > can use $! directly. Otherwise, you can capture it into a variable > and use it in the `kill' command.
So, I tried the following: (echo a > >(cat; sleep 5); echo b > >(cat; sleep 1); wait) which does confirm what you're saying; the command returns after only 1 second, not 5. However, `help wait` states the following (emphasis mine): If ID is not given, waits for all currently active child *processes*, and the return status is zero. And, placing a call to `pstree` just before the `wait` in the above command prints the following: [...]-bash-+-bash---sleep |-bash---sleep `-pstree Which is to say both process substitutions are child processes of the waiting process, therefore `wait` not waiting for the first one seems to me to contradict the above quote. Or, perhaps I'm misunderstanding the meaning of the term "active" in the above quote and for some reason the first process substitution is not to be considered "active"... Even so, I still don't really get the rationale behind only having `wait` wait for the last process substitution alone. After all, it does wait for all other kinds of processes irrespective of when they were started or how many there are, so why the special treatment for process substitutions? This is just really confusing and error-prone —or at least it has been for me, and I fail to see any upsides it. By the way, I did find a workaround for my use case; replacing the following in my trap: kill $(jobs -p) with this: eval "kill \$(ps -o pid= --ppid $BASHPID)" But I still think it would be nice if `wait` and `jobs` behaved more consistently. To sum up, here are the two points I find to be inconsistent: 1. `wait` takes into account process substitutions (or at least the last one) but `jobs` does not. 2. `wait` takes into account only the last process substitution but takes into account all processes of other kinds, not just the last of their kind (and this is not documented in the help or the man page). What are your thoughts on these points? I feel like we should at least be able to agree on point 2., especially in light of the fact that the current behaviour is not even documented. > You should also ensure that you're using bash-5.0 with patch 4 applied, > since that is relevant to this issue. Yep, ubuntu 19.04 is still on bash 5.0.3 but I've been making sure to use the latest version, compiled from master (5.0.7). -- mwnx GPG: AEC9 554B 07BD F60D 75A3 AF6A 44E8 E4D4 0312 C726 ipfs.io/ipfs/QmV4tMgNmqewgcPgX4ktAbrA9jHeiM2DhEFSB4BKxwj75c