pub struct Signal { /* private fields */ }
Expand description
An listener for receiving a particular type of OS signal.
The listener can be turned into a Stream
using SignalStream
.
In general signal handling on Unix is a pretty tricky topic, and this
structure is no exception! There are some important limitations to keep in
mind when using Signal
streams:
-
Signals handling in Unix already necessitates coalescing signals together sometimes. This
Signal
stream is also no exception here in that it will also coalesce signals. That is, even if the signal handler for this process runs multiple times, theSignal
stream may only return one signal notification. Specifically, beforepoll
is called, all signal notifications are coalesced into one item returned frompoll
. Oncepoll
has been called, however, a further signal is guaranteed to be yielded as an item.Put another way, any element pulled off the returned listener corresponds to at least one signal, but possibly more.
-
Signal handling in general is relatively inefficient. Although some improvements are possible in this crate, it’s recommended to not plan on having millions of signal channels open.
If you’ve got any questions about this feel free to open an issue on the repo! New approaches to alleviate some of these limitations are always appreciated!
§Caveats
The first time that a Signal
instance is registered for a particular
signal kind, an OS signal-handler is installed which replaces the default
platform behavior when that signal is received, for the duration of the
entire process.
For example, Unix systems will terminate a process by default when it
receives SIGINT
. But, when a Signal
instance is created to listen for
this signal, the next SIGINT
that arrives will be translated to a stream
event, and the process will continue to execute. Even if this Signal
instance is dropped, subsequent SIGINT
deliveries will end up captured by
Tokio, and the default platform behavior will NOT be reset.
Thus, applications should take care to ensure the expected signal behavior occurs as expected after listening for specific signals.
§Examples
Wait for SIGHUP
use tokio::signal::unix::{signal, SignalKind};
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
// An infinite stream of hangup signals.
let mut sig = signal(SignalKind::hangup())?;
// Print whenever a HUP signal is received
loop {
sig.recv().await;
println!("got signal HUP");
}
}
Implementations§
§impl Signal
impl Signal
pub async fn recv(&mut self) -> Option<()>
pub async fn recv(&mut self) -> Option<()>
Receives the next signal notification event.
None
is returned if no more events can be received by this stream.
§Cancel safety
This method is cancel safe. If you use it as the event in a
tokio::select!
statement and some other branch
completes first, then it is guaranteed that no signal is lost.
§Examples
Wait for SIGHUP
use tokio::signal::unix::{signal, SignalKind};
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
// An infinite stream of hangup signals.
let mut stream = signal(SignalKind::hangup())?;
// Print whenever a HUP signal is received
loop {
stream.recv().await;
println!("got signal HUP");
}
}
pub fn poll_recv(&mut self, cx: &mut Context<'_>) -> Poll<Option<()>>
pub fn poll_recv(&mut self, cx: &mut Context<'_>) -> Poll<Option<()>>
Polls to receive the next signal notification event, outside of an
async
context.
This method returns:
Poll::Pending
if no signals are available but the channel is not closed.Poll::Ready(Some(()))
if a signal is available.Poll::Ready(None)
if the channel has been closed and all signals sent before it was closed have been received.
§Examples
Polling from a manually implemented future
use std::pin::Pin;
use std::future::Future;
use std::task::{Context, Poll};
use tokio::signal::unix::Signal;
struct MyFuture {
signal: Signal,
}
impl Future for MyFuture {
type Output = Option<()>;
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
println!("polling MyFuture");
self.signal.poll_recv(cx)
}
}