14.3 Unkillable Processes
A process in uninterruptible kernel sleep does not respond to SIGKILL. Nothing peinit can do will make it exit, and the design consequence is that peinit stops trying rather than blocking on it.
Detection is uniform: after sending the kill, arm a post-kill deadline (5 seconds by default) and check whether the cgroup still reports as populated when it fires.
What follows depends on which cgroup it was:
| Cgroup | Consequence |
|---|---|
main/ | The service goes to Abandoned with cause ProcessUnkillable. Supervision stops; the cgroup is leaked. |
health/ or hooks/ | The sub-cgroup is orphaned and recorded as a leak. The service carries on normally. |
checks/ | The sub-cgroup is dropped with no record. |
The distinction is about what the stuck process is holding. A main process holds the service's ports, locks and connections, so a service whose main process cannot be killed cannot be restarted into a working state. A health check or a hook holds nothing, so a stuck one is a nuisance rather than a blocker.
14.3.1 What Abandoned means #
peinit has given up. The service is not restarted, does not satisfy
dependents, and every lifecycle command against it is invalid except
reset (§10.3).
A reset re-checks main/. If it has finally emptied — the I/O that
was hung completed, or the device came back — peinit cleans up the whole
tree and the service returns to Inactive. If it is still populated, the
service returns to Inactive anyway, the cgroup stays leaked, and both the
acknowledgement and the console carry a warning saying so.
14.3.2 The generational escape #
A leaked cgroup cannot be removed, so the next start would collide with
it. Recording a leak increments the service's cgroup generation, and the
next start builds a fresh tree at .gen<N> (§5.1). Old trees persist
until reboot.
That is what lets a service recover from a leak at all: peinit cannot clean up the old tree, so it stops trying to and uses a new one.
14.3.3 What it actually means #
Every path here has the same underlying cause. Something below the service — a hung mount, a failing controller, a device that stopped answering — is not responding to the kernel, and no amount of restarting the service will change that. The leak record exists to say so, because the alternative is a service that mysteriously will not restart.