Expand description
Observes guest processes’ physical exits through pidfds, for backends whose processes leave the host some time after their scheduler-granted exit.
Detcore holds only abstract lifetime state; how a process’s exit is observed
on the host belongs to the backend (owner directive 082). A backend hands
this watcher one pidfd per guest process (from pidfd_open, or a socket’s
SO_PEERPIDFD) together with the process id Detcore knows it by. The
watcher calls the backend’s callback with that id exactly once, after the
exit is complete as the guest’s parent can see it; a backend wires the
callback to GlobalState::complete_physical_process_exit.
The pidfd alone is not enough. exit_notify runs under
write_lock_irq(&tasklist_lock): it sets the zombie state, then
do_notify_parent wakes pidfd waiters and only then queues SIGCHLD to the
parent. So when the pidfd becomes readable, the watcher calls
waitid(P_PIDFD, pidfd, WEXITED | WNOHANG | WNOWAIT). While the process is
unreaped, the kernel takes read_lock(&tasklist_lock) for that call
(__do_wait), which cannot be granted until exit_notify’s write section,
and with it the SIGCHLD queueing, has finished. A non-parent gets ECHILD
and nothing is consumed; WNOWAIT leaves a parent’s zombie in place. If
the process was already reaped, release_task ran after that section
anyway. Either way, a parent probing its pending signals or children sees
the exit in every run once it is reported.
The watcher never waits on or reaps a process: the guest’s own parent, or the backend’s launcher for the root, stays the only reaper.
PhysicalExitWatch::new watches on a thread of its own.
PhysicalExitWatch::on_runtime watches on an existing tokio runtime
instead, for a launcher that must not create a thread: in-guest LiteInst’s
coordinator shares the guest’s PID namespace, where every thread takes a
process id the guest would otherwise see.
Structs§
- Physical
Exit Watch - A watcher over a set of pidfds. See the module documentation.
Enums§
- Drain
Error - Why
PhysicalExitWatch::drainreturned without every watched process gone. - Watched
- What
PhysicalExitWatch::watchdid with a registration.
Functions§
- birth_
identity - A process’s birth identity: the inode number of a pidfd for it, when that
is a pidfs inode (Linux 6.9 and later), which is one per process and never
reused while the kernel runs. Before pidfs every pidfd shares one
anonymous inode, which names no process, so there is none. Every pidfd for
the same process has the same inode, however it was obtained
(
pidfd_open,SO_PEERPIDFD,CLONE_PIDFD).