Created
February 14, 2024 10:58
-
-
Save DoumanAsh/258cb344b0cf1c76e6319beecbdf50bf to your computer and use it in GitHub Desktop.
tokio's signal handler to await termination
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
use core::future::Future; | |
use core::pin::Pin; | |
use core::task; | |
use std::io; | |
///Future that resolves when program is requested to terminate | |
#[must_use = "Future does nothing without polling"] | |
pub struct Termination { | |
#[cfg(unix)] | |
term: tokio::signal::unix::Signal, | |
#[cfg(unix)] | |
interrupt: tokio::signal::unix::Signal, | |
#[cfg(windows)] | |
interrupt: tokio::signal::windows::CtrlC, | |
} | |
impl Termination { | |
#[inline] | |
///Creates termination future, returning error if underlying signal handler cannot be created | |
pub fn new() -> io::Result<Self> { | |
Ok(Self { | |
#[cfg(unix)] | |
term: tokio::signal::unix::signal(tokio::signal::unix::SignalKind::terminate())?, | |
#[cfg(unix)] | |
interrupt: tokio::signal::unix::signal(tokio::signal::unix::SignalKind::interrupt())?, | |
#[cfg(windows)] | |
interrupt: tokio::signal::windows::ctrl_c()?, | |
}) | |
} | |
} | |
impl Future for Termination { | |
type Output = (); | |
fn poll(self: Pin<&mut Self>, ctx: &mut task::Context<'_>) -> task::Poll<Self::Output> { | |
let this = self.get_mut(); | |
#[cfg(unix)] | |
{ | |
if let task::Poll::Ready(Some(())) = this.term.poll_recv(ctx) { | |
tracing::info!("Termination"); | |
return task::Poll::Ready(()); | |
} | |
} | |
if let task::Poll::Ready(Some(())) = this.interrupt.poll_recv(ctx) { | |
tracing::info!("Interrupt"); | |
return task::Poll::Ready(()); | |
} | |
task::Poll::Pending | |
} | |
} | |
#[tracing::instrument] | |
///Await for process to be terminated or interrupted. | |
/// | |
///If signal handler cannot be installed, wait forever | |
pub async fn await_termination() { | |
match Termination::new() { | |
Ok(termination) => { | |
termination.await; | |
} | |
Err(error) => { | |
tracing::error!(%error, "Cannot monitor for termination"); | |
core::future::pending().await | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment