use crate::options::structs::CustomError; use std::sync::Arc; use tokio::io; use tokio::sync::mpsc; use tokio::{ select, signal::unix::{signal, Signal, SignalKind}, }; type SendersVec = Arc>>>; pub async fn set_valid_destructor(senders: SendersVec) -> Result<(), CustomError> { let (mut int, mut term, mut stop) = ( Sig::new(Signals::Sigint, senders.clone()), Sig::new(Signals::Sigterm, senders.clone()), Sig::new(Signals::Sigstop, senders.clone()), ); select! { _ = int.post_processing() => {log::info!("Initializing interruption...")}, _ = term.post_processing() => {log::info!("Initializing termination...")}, _ = stop.post_processing() => {log::info!("Initializing freezing...")}, } Ok(()) } enum Signals { Sigint, Sigterm, Sigstop, } struct Sig { signal: Signal, sig_type: Signals, senders: SendersVec, } impl Sig { fn new(signal_type: Signals, sends: SendersVec) -> Self { Sig { signal: signal_type.get_signal().unwrap(), sig_type: signal_type, senders: sends, } } } impl std::fmt::Display for Signals { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { match self { Signals::Sigint => write!(f, "SIGINT"), Signals::Sigterm => write!(f, "SIGTERM"), Signals::Sigstop => write!(f, "SIGSTOP"), } } } impl Signals { fn get_signal(&self) -> io::Result { match self { Signals::Sigint => signal(SignalKind::interrupt()), Signals::Sigterm => signal(SignalKind::terminate()), Signals::Sigstop => signal(SignalKind::quit()), } } } trait SigPostProcessing { async fn post_processing(&mut self) -> io::Result<()>; } impl SigPostProcessing for Sig { async fn post_processing(&mut self) -> io::Result<()> { // manipulations ... if self.signal.recv().await.is_some() { log::info!("Got {} signal", self.sig_type); for prc in self.senders.clone().iter() { let _ = prc.send(111).await; } } Ok(()) } } #[cfg(test)] mod signals_unittest { use super::*; #[tokio::test] async fn get_signal_check() { assert!(Signals::Sigint.get_signal().is_ok()) } }