[Top][All Lists]

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

Re: 5.0 regression: Script stuck when waiting in trap

From: mwnx
Subject: Re: 5.0 regression: Script stuck when waiting in trap
Date: Thu, 6 Jun 2019 09:57:24 +0200
User-agent: Mutt/1.9.4 (2018-02-28)

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:


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

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).

GPG: AEC9 554B 07BD F60D 75A3  AF6A 44E8 E4D4 0312 C726

reply via email to

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