pub struct Waiter { /* private fields */ }Expand description
An object that buffers SIGCHLD signals so that you can wait on them reliably.
Waiter can’t tell you which process woke you up, so you usually need to wait in a loop and
poll your Child each time through. One way to make sure you don’t miss a signal
(and potentially wait forever) is to create a Waiter before you spawn your child process,
like this:
let mut waiter = sigchld::Waiter::new()?;
// Any SIGCHLD after this point will be buffered by the Waiter.
let mut child = std::process::Command::new("sleep").arg("1").spawn()?;
loop {
waiter.wait()?;
// *Some* child has exited. Check whether it was our child.
if child.try_wait()?.is_some() {
break;
}
}
// Our child has exited.If you create a Waiter after your child is already running, then you need to poll the child
at least once before you wait:
let mut child = std::process::Command::new("sleep").arg("1").spawn()?;
// If SIGCHLD arrives here, before the Waiter is created, we could miss it.
let mut waiter = sigchld::Waiter::new()?;
while child.try_wait()?.is_none() {
// Now we know the child didn't exit before we created the Waiter.
waiter.wait()?;
}
// Our child has exited.The following order of operations is broken. You could miss SIGCHLD and wait forever:
let mut child = std::process::Command::new("sleep").arg("1").spawn()?;
// If SIGCHLD arrives now, before the Waiter is created, we could miss it.
let mut waiter = sigchld::Waiter::new()?;
// OOPS: If we missed SIGCHLD, we'll wait forever.
waiter.wait()?;Most applications will prefer higher-level APIs like
shared_child or duct, where you
don’t have to worry about this sort of mistake. This crate is intended more as a building block
for those APIs.
Implementations§
Source§impl Waiter
impl Waiter
Sourcepub fn new() -> Result<Self>
pub fn new() -> Result<Self>
Create a Waiter.
Any SIGCHLD signals that arrive after a Waiter is created, but before a call to
wait, wait_timeout, or
wait_deadline, will be buffered. In that case the next call to one
of those methods will return immediately. Note that each wait clears the entire buffer, so
a single wakeup could indicate that multiple signals arrived. In other words, signals can
be “coalesced”.
Sourcepub fn wait(&mut self) -> Result<()>
pub fn wait(&mut self) -> Result<()>
Block the current thread until any SIGCHLD signal arrives.
If any SIGCHLD signals have arrived since the Waiter was created, this function will
return immediately. This avoids a race condition where the child exits right after you call
Child::try_wait but right before you call this function.
This function does not reap any exited children. Child process cleanup is only done by
Child::wait or Child::try_wait.
This function is not currently susceptible to “spurious wakeups” (i.e. returning early for no reason), but this property isn’t guaranteed, and future versions might be. Getting woken up early by an unrelated child process exiting (e.g. one spawned by some unknown library code running on another thread) is similar to a spurious wakeup, and you might need to be defensive and wait in a loop either way.
Sourcepub fn wait_timeout(&mut self, timeout: Duration) -> Result<bool>
pub fn wait_timeout(&mut self, timeout: Duration) -> Result<bool>
Block the current thread until either any SIGCHLD signal arrives or a timeout passes.
Return true if a signal arrived before the timeout.
If any SIGCHLD signals have arrived since the Waiter was created, this function will
return immediately. This avoids a race condition where the child exits right after you call
Child::try_wait but right before you call this function.
This function does not reap any exited children. Child process cleanup is only done by
Child::wait or Child::try_wait.
This function is not currently susceptible to “spurious wakeups” (i.e. returning early for no reason), but this property isn’t guaranteed, and future versions might be. Getting woken up early by an unrelated child process exiting (e.g. one spawned by some unknown library code running on another thread) is similar to a spurious wakeup, and you might need to be defensive and wait in a loop either way.
Sourcepub fn wait_deadline(&mut self, deadline: Instant) -> Result<bool>
pub fn wait_deadline(&mut self, deadline: Instant) -> Result<bool>
Block the current thread until either any SIGCHLD signal arrives or a deadline passes.
Return true if a signal arrived before the deadline.
If any SIGCHLD signals have arrived since the Waiter was created, this function will
return immediately. This avoids a race condition where the child exits right after you call
Child::try_wait but right before you call this function.
This function does not reap any exited children. Child process cleanup is only done by
Child::wait or Child::try_wait.
This function is not currently susceptible to “spurious wakeups” (i.e. returning early for no reason), but this property isn’t guaranteed, and future versions might be. Getting woken up early by an unrelated child process exiting (e.g. one spawned by some unknown library code running on another thread) is similar to a spurious wakeup, and you might need to be defensive and wait in a loop either way.