bug-bash
[Top][All Lists]
Advanced

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

Re: 'wait -n' with and without id arguments


From: Robert Elz
Subject: Re: 'wait -n' with and without id arguments
Date: Thu, 22 Aug 2024 05:55:31 +0700

    Date:        Wed, 21 Aug 2024 11:00:19 -0400
    From:        Chet Ramey <chet.ramey@case.edu>
    Message-ID:  <1b229634-888f-4f06-8761-c16d62501c06@case.edu>

  | POSIX doesn't actually say that. It says, in a couple of different places,
  | "the message shall be written immediately prior to writing the next prompt
  | for input," which implies that you should write messages before $PS2 also.

OK, I'll do a little testing later and work out what it ought to be saying -
but for present purposes that difference is immaterial.  The shell (any shell)
execution sequence is to read & parse a (wording is hard here, as there are so
many terms defined in different places, and I don't mean any of them) a full
command, then execute it, and repeat until either there is no more input, or
execution of the command causes the shell to terminate.

The process of reading that full command in an interactive shell is to outout
PS1, read a line from the input stream, and if more is needed, output PS2,
read more, ... until there is sufficient input.   During this whole time, the
shell is doing nothing except waiting for that command to be ready to execute
(which needs all its pieces to be available - including here doc data).

The notification of an old job's change in status could happen at any point
during this sequence, before the command input actually starts executing,
that cannot possibly make any logical difference to anything pertinent here.

Once the command is executing, only actions of that command (or sequence of
commnds) (and just possibly -b) should cause any change in status of any job,
until execution is finished, and the shell is ready to prompt for the next of
them.

[Aside: it is possible that there might be something which causes a trap and
evaluation of a trap action - but that's immaterial for present purposes as
no prompts are issued for that - and if -b is set, the shell might notify the
user of a background command completing, there's almost nothing in the standard
about what that actually means, but it is also immaterial, as even if that does
count as a "jobs" type notification - which the standard doesn't say - that
is no different than if the notification had been because of a prompt output].

What matters here is that a wait -n (with or without pid args - that difference
just limits which jobs are candidates to be consumed) can find any process
which has terminated (or in bash, stopped) which has not otherwise been
notified.  ie: none of the jobs are "hidden" because of some earlier action
(like having terminated before the wait command was issued, unless they were
also earlier waited upon or jobs type notified).

Beyond that, what happens is much less important - personally I think it is a
mistake to keep anything about terminated jobs after they have been consumed
by a wait or jobs command, they need to be deleted eventually, or the shell
will just keep consuming more memory forever, until it exhausts the available
memory resources, and can't do anything at all.   There are no other (standard
anyway) mechanisms to clean out ancient stuff, except for the "only need to
retain CHILD_MAX" (or whatever it is) limit, which is a horrible thing to do
to the user, as they have no real control over that (and I suspect is only
there because ancient shells used to do that, not because anyone desires it).
Having old jobs still available for wait, at one instant, and then no longer
available a little later, as the shell needed to clean them up, is useless.

The test here should be that in a command like

        wait; set +b; for i in {1..1000} ; do sleep 0.01 & X=$!
        done; for i in {1..1000} ; do wait -p pid -n ||
        printf "process %s failed: status %s\n" "${pid:-X}" "$?"
        done

there should be no output at all (unless for some reason sleep were to
actually fail).   Reduce the 1000 to something smaller if you really want
the CHILD_MAX type limitation.   The assignment to X is just so the other
useless standards restriction, of not needing to remember background jobs
unless $! has been read (also ancient stupidity) is handled.   The odd
formatting is just so that this is all one "full command" (1 PS1 and 3 PS2's).
If "sleep 0.01" doesn't work, then use "(exit 0)" instead, or anything which
is quick enough, and should result in a zero exit status, and for which at
least some of the jobs will have terminated before the second loop starts
running.   The wait at the start is just to clean out any earlier pending
(or running) background jobs, so they don't interfere.  set +b is to avoid
anything that having -b set might do to alter the behaviour.

A real application would be more complex of course, and probably embedded
in a function, but this is the essence of what should work.   And yes, I am
assuming a shell which does brace expansion, and that is enabled, but that's
trivial to replace with a command sub which produces N (1000 or whatever) words
if needed, what those words are is immaterial for this ... $i is not used.

kre



reply via email to

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