Skip to main content

Module physical_exit_watch

Module physical_exit_watch 

Source
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§

PhysicalExitWatch
A watcher over a set of pidfds. See the module documentation.

Enums§

DrainError
Why PhysicalExitWatch::drain returned without every watched process gone.
Watched
What PhysicalExitWatch::watch did 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).