Documentation
¶
Overview ¶
Package reaper reaps orphaned child processes when this process is PID 1.
In a container, the kernel reparents every orphan (a daemon that double-forked, a background job whose shell exited, whatever escaped a killed process group) to PID 1. Only a wait call by PID 1 removes such a process once it exits; without one it stays a zombie for the life of the container. Zombies keep their pid, still answer kill -0, [ -e /proc/PID ] and pgrep, so a script waiting for a stopped daemon to disappear never finishes, and ps shows <defunct> entries.
Go's exec.Cmd waits on exactly the child it started, so a process started with exec.Cmd must not be reaped here: cmd.Wait would fail with "no child processes" and lose the exit status. Two mechanisms keep them apart:
- StartCmd tracks the pid under the same lock the reap loop takes, so a child cannot exit and be reaped between Start and being recorded.
- Children Go holds a pidfd for (every exec.Cmd on kernels with pidfd support) are recognised through /proc/self/fdinfo and skipped even when nobody called StartCmd for them.
A child started with plain exec.Cmd on a kernel without pidfd support has neither protection and can lose its status if it exits at the moment the reap loop runs; callers that must be safe there use StartCmd.
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func StartCmd ¶
StartCmd starts cmd and marks its process as owned by an exec.Cmd so the reap loop leaves it to cmd.Wait. Pair with Untrack once Wait has returned.
func StartIfInit ¶
func StartIfInit()
StartIfInit starts the reap loop for the lifetime of the process when this process is PID 1. It is a no-op otherwise and on repeated calls.
Types ¶
This section is empty.