1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
//! Forked-child cleanup helpers shared across [`super::SpawnGuard`]'s
//! drop path, mid-spawn early-bail, and `stop_and_collect`'s per-child
//! SIGKILL escalation.
//!
//! Each helper centralises a duplicated cleanup pattern from `mod.rs`
//! so a future addition (new signal, new fd-class to close, new errno
//! to swallow) lands in one place instead of drifting across six call
//! sites. Every errno is swallowed silently — the caller contexts are
//! mid-cleanup-on-error paths where there is nothing to assert against
//! beyond not leaking. See each helper's doc for the specific
//! swallow rationale.
use RawFd;
use Signal;
use Pid;
/// Silently close every fd in `fds` that is `>= 0`. Negative-fd
/// entries (sentinel values for "this slot was never opened" inside
/// `ChildHandle::report_fd` / `start_fd`) are skipped so callers can
/// mix opened and never-opened fds in the same slice without
/// special-casing each one. `EBADF` from a double-close is swallowed
/// because the cleanup paths share fd state with the success path
/// that may have already closed inherited copies — and from the
/// child side of a fork that has already closed its inherited copy
/// before the parent's cleanup runs.
pub
/// Send `signal` to `pid` AND to the process group led by `pid` via
/// `killpg(2)`. Used in `stop_and_collect`'s per-child SIGKILL
/// escalation: the worker fork tree includes any grandchildren the
/// worker spawned (e.g. `WakeChain`'s pipeline stages), and the
/// framework's `setsid()` boundary in the worker child means a
/// direct `kill(pid, ...)` reaches only the leader. The paired
/// `killpg` fans out to every process in the leader's session group
/// so the fork tree dies as a unit, not "leader gone, orphans
/// reparented to init."
///
/// Both calls swallow errors:
/// - `ESRCH` from `kill` fires when the leader has already exited
/// (whether running-then-exited or auto-reaped under the
/// SIGCHLD=SIG_IGN convention — either way the pid slot is gone
/// from the kernel's process table). The `killpg` still reaches
/// surviving group members.
/// - `ESRCH` from `killpg` fires on an empty group (last member
/// exited) — nothing to do.
/// - `EPERM` is not expected under normal teardown: ktstr runs as
/// root (CAP_KILL always present per the always-root project
/// contract), so the only ways `kill` refuses are non-root
/// callers or PID 1 / kernel threads, neither of which apply to
/// forked workers. The `let _ =` ignore covers the EPERM case
/// anyway as a defensive belt against a future non-root run
/// mode.
pub