Skip to main content

ProcessGroupGuard

Struct ProcessGroupGuard 

Source
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

Source

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.

Source

pub const fn process_group(&self) -> ProcessGroupId

Return the reserved group which a prepared workload must join.

Source

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.

Source

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.

Source

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.

Source

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.

Trait Implementations§

Source§

impl Debug for ProcessGroupGuard

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Drop for ProcessGroupGuard

Source§

fn drop(&mut self)

Executes the destructor for this type. Read more
Source§

fn pin_drop(self: Pin<&mut Self>)

🔬This is a nightly-only experimental API. (pin_ergonomics)
Execute the destructor for this type, but different to Drop::drop, it requires self to be pinned. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, !>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.