Sujet : Re: (bash) How (really!) does the "current job" get determined?
De : 643-408-1753 (at) *nospam* kylheku.com (Kaz Kylheku)
Groupes : comp.unix.shellDate : 08. Oct 2024, 18:37:20
Autres entêtes
Organisation : A noiseless patient Spider
Message-ID : <20241008101759.180@kylheku.com>
References : 1 2 3 4 5 6 7
User-Agent : slrn/pre1.0.4-9 (Linux)
On 2024-10-04, Christian Weisgerber <
naddy@mips.inka.de> wrote:
What happens if the background job has already terminated on its
own accord before we reach the kill(1)? Not much, because with job
control, the shell knows that no such job exists.
In Unix, when a child process terminates, it does not go away. The parent
process has to call one of the wait functions like waitpid in order to "reap"
that process. It can be notified of children in this state asynchronously via
the SIGCHLD signal.
The problem of PIDs suddenly disappearing and being recycled behind the parent
process' back does not exist in the operating system.
We can imagine a shell which does nothing when a child coprocess launched with
& terminates spontaneously, so that the script /must/ use the wait command.
In that shell, the process ID of that child will remain reliably available
until that wait.
Only if the shell reaps terminated coprocesses behind the script's back, so to
speak, do you have the reuse problem.
What does POSIX say? Something between those two alternatives:
When an element of an asynchronous list (the portion of the list ended
by an <ampersand>, such as command1, above) is started by the shell, the
process ID of the last command in the asynchronous list element shall
become known in the current shell execution environment; see Shell
Execution Environment. This process ID shall remain known until:
The command terminates and the application waits for the process ID.
Another asynchronous list is invoked before "$!" (corresponding to
the previous asynchronous list) is expanded in the current execution
environment.
The implementation need not retain more than the {CHILD_MAX} most
recent entries in its list of known process IDs in the current shell
execution environment.
It's seems as if what POSIX is saying is that scripts which fire off
asynchronous jobs one after another receive automatic clean up.
A script which does not refer to the $! variable from one ampersand
job, before firing off more ampersand jobs, will not clog the system
with uncollected zombie processes. But a script which does reference $!
after launching an ampersand job (before launching another one) will not
have that process cleaned up behind its back: it takes on the responsibility
for doing the wait which recycles the PID.
Anyway, that's what I'd like to believe that the quoted passage means.
If you do this
with "kill $!", you signal that PID, which no longer refers to the
intended process and may in fact have been reused for a different
process.
At the system call level, that's not what kill means. It means to
pass a certain signal (fatal or not, catchable or not) to the process.
Even if the signal is uncatchable and fatal, kill deos not mean
"make the target process disappear, so that its PID may be reused".
The waitpid system call will do that (in the situation when the process
is a zombie, and so subsequently the returned status indicates that
it exited, and with what exit code or on what signal).
-- TXR Programming Language: http://nongnu.org/txrCygnal: Cygwin Native Application Library: http://kylheku.com/cygnalMastodon: @Kazinator@mstdn.ca