pub struct ProcessGroupGuard { /* private fields */ }Expand description
An owned fail-closed capability for one reserved process group.
While its helper lives, the guard pins its group: an unreaped anchor zombie
stays a member, so crate::process_group_exists reports it present until
Self::disarm. Use Self::signal_group while armed: direct group signals
are unsafe if an unobserved helper death has released the pin.
Dropping an armed value closes the owner socket. The out-of-group helper then sends SIGKILL to the
group and is reaped within the caller’s process. Call Self::activate
only after the workload has successfully joined the reserved group, and
Self::disarm only after the group no longer requires broker-death
containment. Cleanup resumes a stopped helper and waits up to three seconds
before killing the helper; its final reap waits for kernel progress and is
not absolutely bounded. With owner SIGCHLD ignored or SA_NOCLDWAIT set,
creation and helper-mediated group delivery still work, but cleanup refuses
helper PID signals: it cannot resume or kill a stopped helper. The socket is
still closed, so a running helper can finish cleanup itself. A helper that
cannot run cannot guarantee group cleanup.
This capability contains process-group membership, not arbitrary descendants. A workload which creates a session or changes group has left the portable boundary. Disarming releases the pin: once disarmed, an empty group’s ID may be reused, so it must never be signalled again.
Implementations§
Source§impl ProcessGroupGuard
impl ProcessGroupGuard
Sourcepub fn new() -> Result<Self>
pub fn new() -> Result<Self>
Reserve and pin a process group under an out-of-group owner-loss guard.
Call this from a dedicated single-threaded process broker. The returned
value exclusively owns one direct helper child, which in turn owns the
group’s anchor until the guard is disarmed or dropped. An auto-reaping
owner is accepted, without changing its policy; the helper owns its own
waitable anchor. For owner-side cleanup signals keep SIGCHLD non-ignored
and SA_NOCLDWAIT unset, and serialize policy changes and collection.
§Errors
Returns an operating-system error if descriptor preparation, the helper
fork, or group reservation fails. The helper reports the errno with
which it failed to close inherited descriptors or to create or confirm
the anchor, such as EACCES from a sandbox; on targets that spawn the
anchor (macOS among them) a missing or exec-denied /usr/bin/true
returns the spawn error. TimedOut means the helper did not report in
time, and UnexpectedEof that it exited without reporting. A started
helper’s socket is closed; numeric-PID cleanup is attempted only while
waitable ownership is proven. An auto-reaping owner cannot resume or kill
a stopped helper and may need its own cleanup coordination.
Sourcepub const fn process_group(&self) -> ProcessGroupId
pub const fn process_group(&self) -> ProcessGroupId
Return the reserved group which a prepared workload must join.
Sourcepub const fn guard_process(&self) -> ProcessId
pub const fn guard_process(&self) -> ProcessId
Return the persistent helper process for exact wait-event routing.
This identifier is for classifying events in a broker-owned all-child wait loop. Helper cleanup and event collection must be serialized. A terminal helper event means containment failed; do not treat it as a normal workload exit.
Sourcepub fn activate(&mut self, timeout: Duration) -> Result<()>
pub fn activate(&mut self, timeout: Duration) -> Result<()>
Record that the workload has joined the group.
The group is reserved and pinned from Self::new onward, so
activation changes no process state; it keeps the activation order
explicit for callers. timeout is validated for source compatibility
with 0.10.0 and is otherwise unused.
§Errors
Returns InvalidInput for a zero or out-of-range timeout, or for a
repeated activation. The guard stays armed either way.
Sourcepub fn signal_group(&self, signal: Signal, timeout: Duration) -> Result<()>
pub fn signal_group(&self, signal: Signal, timeout: Duration) -> Result<()>
Signal the group through the helper while it holds the unreaped anchor.
Never signal the numeric group directly while armed: an unobserved
helper death may have released its pin. Calls are serialized, including
concurrent shared borrows. A timeout does not cancel a queued signal;
it may still be delivered later. Ok means the helper delivered this
exact request. Unique request IDs prevent stale replies, including for
the same signal, from acknowledging a later request.
§Errors
Returns InvalidInput for zero/oversized timeouts, a missing owner, or
exhaustion of the guard’s non-reused u32 request IDs,
TimedOut at the deadline, and BrokenPipe/UnexpectedEof if the helper
is gone (the group must not then be signalled directly). Otherwise returns
the helper’s kill errno, including macOS EPERM for an anchor-only group.
Sourcepub fn disarm(self, timeout: Duration) -> Result<()>
pub fn disarm(self, timeout: Duration) -> Result<()>
Disarm the helper and release the group’s pin without signaling it.
§Errors
Returns InvalidInput for a zero/oversized timeout or an auto-reaping
owner policy, or a write, wait,
unexpected-status, or deadline error. Consuming failure remains
fail-closed. Cleanup resumes a stopped helper until the deadline, then
kills it; the final reap waits for the kernel and has no absolute bound.
If the owner violated the waitable-child policy, the socket is still
closed but cleanup never signals a potentially reused helper PID. A
stopped helper then cannot be resumed by this guard.