exit listener

This commit is contained in:
Love 2024-07-25 20:46:30 +02:00
parent 5466090256
commit f34c4609a5
3 changed files with 50 additions and 22 deletions

43
src/exit_listener.rs Normal file
View File

@ -0,0 +1,43 @@
use std::sync::{
atomic::{AtomicBool, Ordering},
Arc,
};
use tokio::{
self, signal,
sync::{futures::Notified, Notify},
};
pub struct ExitListener {
should_exit: Arc<AtomicBool>,
notify: Arc<Notify>,
}
impl ExitListener {
pub fn new() -> Self {
let this = Self {
should_exit: Arc::new(AtomicBool::new(false)),
notify: Arc::new(Notify::new()),
};
let should_exit = this.should_exit.clone();
let notify = this.notify.clone();
tokio::spawn(async move {
signal::ctrl_c()
.await
.expect("Failed to install CTRL+C signal handler");
should_exit.store(true, Ordering::SeqCst);
notify.notify_one();
});
this
}
pub fn notified(&self) -> Notified<'_> {
self.notify.notified()
}
pub fn should_exit(&self) -> bool {
self.should_exit.load(Ordering::SeqCst)
}
}

View File

@ -2,6 +2,7 @@
mod cloudflare; mod cloudflare;
mod config; mod config;
mod exit_listener;
mod logging; mod logging;
mod message_handler; mod message_handler;
mod public_ip; mod public_ip;
@ -10,6 +11,7 @@ pub mod utils;
pub use cloudflare::CloudflareClient; pub use cloudflare::CloudflareClient;
pub use config::{get_config_path, read_config, Config}; pub use config::{get_config_path, read_config, Config};
pub use exit_listener::ExitListener;
pub use logging::init_logger; pub use logging::init_logger;
pub use message_handler::MessageHandler; pub use message_handler::MessageHandler;
pub use public_ip::get_current_public_ipv4; pub use public_ip::get_current_public_ipv4;

View File

@ -1,11 +1,6 @@
// SPDX: BSD-2-Clause // SPDX: BSD-2-Clause
use futures::future::{self, Either}; use futures::future::{self, Either};
use std::sync::{
atomic::{AtomicBool, Ordering},
Arc,
};
use futures::stream::StreamExt; use futures::stream::StreamExt;
use log::{error, info}; use log::{error, info};
use netlink_sys::{AsyncSocket, SocketAddr}; use netlink_sys::{AsyncSocket, SocketAddr};
@ -13,10 +8,10 @@ use rtnetlink::new_connection;
use dynip_cloudflare::{ use dynip_cloudflare::{
utils::{self, duration_to_string}, utils::{self, duration_to_string},
CloudflareClient, MessageHandler, MAX_ERORS_IN_ROW_DEFAULT, CloudflareClient, ExitListener, MessageHandler, MAX_ERORS_IN_ROW_DEFAULT,
}; };
use scopeguard::defer; use scopeguard::defer;
use tokio::{signal, sync::Notify, time}; use tokio::time;
const RTNLGRP_LINK: u32 = 1; const RTNLGRP_LINK: u32 = 1;
const RTNLGRP_IPV4_IFADDR: u32 = 5; const RTNLGRP_IPV4_IFADDR: u32 = 5;
@ -38,19 +33,7 @@ async fn main() {
defer! { defer! {
log::logger().flush(); log::logger().flush();
} }
let should_exit = Arc::new(AtomicBool::new(false)); let exit_listener = ExitListener::new();
let notify = Arc::new(Notify::new());
let should_exit_clone = should_exit.clone();
let notify_clone = notify.clone();
tokio::spawn(async move {
signal::ctrl_c()
.await
.expect("Failed to install CTRL+C signal handler");
should_exit_clone.store(true, Ordering::SeqCst);
notify_clone.notify_one();
});
let config = if let Some(aux) = utils::get_config().await { let config = if let Some(aux) = utils::get_config().await {
aux aux
@ -91,14 +74,14 @@ async fn main() {
interval interval
}); });
while !should_exit.load(Ordering::SeqCst) { while !exit_listener.should_exit() {
let tick_future = match interval.as_mut() { let tick_future = match interval.as_mut() {
Some(interval) => Either::Left(interval.tick()), Some(interval) => Either::Left(interval.tick()),
None => Either::Right(future::pending::<tokio::time::Instant>()), None => Either::Right(future::pending::<tokio::time::Instant>()),
}; };
tokio::select! { tokio::select! {
_ = notify.notified() => break, _ = exit_listener.notified() => break,
_ = tick_future => { _ = tick_future => {
if let Some(duration) = config.max_duration.as_ref() { if let Some(duration) = config.max_duration.as_ref() {
let duration_string = duration_to_string(duration); let duration_string = duration_to_string(duration);