pub async fn listen_for_shutdown(&self) -> Result<(), Error> {
        const GRACEFUL_SHUTDOWN: usize = 1;
        const TERMINATE: usize = 2;

        enum SignalShutdownState {
            Running,
            ShuttingDown(flume::Receiver<()>),
        }

        let shutdown_state = Arc::new(Mutex::new(SignalShutdownState::Running));
        let flag = Arc::new(AtomicUsize::default());
        let register_hook = |flag: &Arc<AtomicUsize>| {
            signal_hook::flag::register_usize(SIGINT, flag.clone(), GRACEFUL_SHUTDOWN)?;
            signal_hook::flag::register_usize(SIGTERM, flag.clone(), TERMINATE)?;
            #[cfg(not(windows))]
            signal_hook::flag::register_usize(SIGQUIT, flag.clone(), TERMINATE)?;
            Result::<(), std::io::Error>::Ok(())
        };
        if let Err(err) = register_hook(&flag) {
            log::error!("Error installing signals for graceful shutdown: {:?}", err);
            tokio::time::sleep(Duration::MAX).await;
        } else {
            loop {
                match flag.load(Ordering::Relaxed) {
                    0 => {
                        // No signal
                    }
                    GRACEFUL_SHUTDOWN => {
                        let mut state = fast_async_lock!(shutdown_state);
                        match *state {
                            SignalShutdownState::Running => {
                                log::error!("Interrupt signal received. Shutting down gracefully.");
                                let task_server = self.clone();
                                let (shutdown_sender, shutdown_receiver) = flume::bounded(1);
                                tokio::task::spawn(async move {
                                    task_server.shutdown(Some(Duration::from_secs(30))).await?;
                                    let _ = shutdown_sender.send(());
                                    Result::<(), Error>::Ok(())
                                });
                                *state = SignalShutdownState::ShuttingDown(shutdown_receiver);
                            }
                            SignalShutdownState::ShuttingDown(_) => {
                                // Two interrupts, go ahead and force the shutdown
                                break;
                            }
                        }
                    }
                    TERMINATE => {
                        log::error!("Quit signal received. Shutting down.");
                        break;
                    }
                    _ => unreachable!(),
                }

                let state = fast_async_lock!(shutdown_state);
                if let SignalShutdownState::ShuttingDown(receiver) = &*state {
                    if receiver.try_recv().is_ok() {
                        // Fully shut down.
                        return Ok(());
                    }
                }

                tokio::time::sleep(Duration::from_millis(300)).await;
            }
            self.shutdown(None).await?;
        }

        Ok(())
    }
/// Listens for signals from the operating system that the server should
/// shut down and attempts to gracefully shut down.
Listens for signals from the operating system that the server should
shut down and attempts to gracefully shut down.
Listens for signals from the operating system that the server should shut down and attempts to gracefully shut down .
pub async fn listen_for_shutdown(&self) -> Result<(), Error> {
        const GRACEFUL_SHUTDOWN: usize = 1;
        const TERMINATE: usize = 2;
        enum SignalShutdownState {
            Running,
            ShuttingDown(flume::Receiver<()>),
        }
        let shutdown_state = Arc::new(Mutex::new(SignalShutdownState::Running));
        let flag = Arc::new(AtomicUsize::default());
        let register_hook = |flag: &Arc<AtomicUsize>| {
            signal_hook::flag::register_usize(SIGINT, flag.clone(), GRACEFUL_SHUTDOWN)?;
            signal_hook::flag::register_usize(SIGTERM, flag.clone(), TERMINATE)?;
            #[cfg(not(windows))]
            signal_hook::flag::register_usize(SIGQUIT, flag.clone(), TERMINATE)?;
            Result::<(), std::io::Error>::Ok(())
        };
        if let Err(err) = register_hook(&flag) {
            log::error!("Error installing signals for graceful shutdown: {:?}", err);
            tokio::time::sleep(Duration::MAX).await;
        } else {
            loop {
                match flag.load(Ordering::Relaxed) {
                    0 => {
                        // No signal
                    }
                    GRACEFUL_SHUTDOWN => {
                        let mut state = fast_async_lock!(shutdown_state);
                        match *state {
                            SignalShutdownState::Running => {
                                log::error!("Interrupt signal received. Shutting down gracefully.");
                                let task_server = self.clone();
                                let (shutdown_sender, shutdown_receiver) = flume::bounded(1);
                                tokio::task::spawn(async move {
                                    task_server.shutdown(Some(Duration::from_secs(30))).await?;
                                    let _ = shutdown_sender.send(());
                                    Result::<(), Error>::Ok(())
                                });
                                *state = SignalShutdownState::ShuttingDown(shutdown_receiver);
                            }
                            SignalShutdownState::ShuttingDown(_) => {
                                // Two interrupts, go ahead and force the shutdown
                                break;
                            }
                        }
                    }
                    TERMINATE => {
                        log::error!("Quit signal received. Shutting down.");
                        break;
                    }
                    _ => unreachable!(),
                }
                let state = fast_async_lock!(shutdown_state);
                if let SignalShutdownState::ShuttingDown(receiver) = &*state {
                    if receiver.try_recv().is_ok() {
                        // Fully shut down.
                        return Ok(());
                    }
                }
                tokio::time::sleep(Duration::from_millis(300)).await;
            }
            self.shutdown(None).await?;
        }
        Ok(())
    }
pub async fn listen_for_shutdown ( & self ) -> Result < ( ) , Error > { const GRACEFUL_SHUTDOWN : usize = 1 ; const TERMINATE : usize = 2 ; enum SignalShutdownState { Running , ShuttingDown ( flume :: Receiver < ( ) > ) , } let shutdown_state = Arc :: new ( Mutex :: new ( SignalShutdownState :: Running ) ) ; let flag = Arc :: new ( AtomicUsize :: default ( ) ) ; let register_hook = | flag : & Arc < AtomicUsize > | { signal_hook :: flag :: register_usize ( SIGINT , flag . clone ( ) , GRACEFUL_SHUTDOWN ) ? ; signal_hook :: flag :: register_usize ( SIGTERM , flag . clone ( ) , TERMINATE ) ? ; # [ cfg ( not ( windows ) ) ] signal_hook :: flag :: register_usize ( SIGQUIT , flag . clone ( ) , TERMINATE ) ? ; Result :: < ( ) , std :: io :: Error > :: Ok ( ( ) ) } ; if let Err ( err ) = register_hook ( & flag ) { log :: error ! ( " " err ) ; tokio :: time :: sleep ( Duration :: MAX ) . await ; } else { loop { match flag . load ( Ordering :: Relaxed ) { 0 => { // No signal } GRACEFUL_SHUTDOWN => { let mut state = fast_async_lock ! ( shutdown_state ) ; match * state { SignalShutdownState :: Running => { log :: error ! ( " " ) ; let task_server = self . clone ( ) ; let ( shutdown_sender , shutdown_receiver ) = flume :: bounded ( 1 ) ; tokio :: task :: spawn ( async move { task_server . shutdown ( Some ( Duration :: from_secs ( 30 ) ) ) . await ? ; let _ = shutdown_sender . send ( ( ) ) ; Result :: < ( ) , Error > :: Ok ( ( ) ) } ) ; * state = SignalShutdownState :: ShuttingDown ( shutdown_receiver ) ; } SignalShutdownState :: ShuttingDown ( _ ) => { // Two interrupts, go ahead and force the shutdown break ; } } } TERMINATE => { log :: error ! ( " " ) ; break ; } _ => unreachable ! ( ) , } let state = fast_async_lock ! ( shutdown_state ) ; if let SignalShutdownState :: ShuttingDown ( receiver ) = & * state { if receiver . try_recv ( ) . is_ok ( ) { // Fully shut down. return Ok ( ( ) ) ; } } tokio :: time :: sleep ( Duration :: from_millis ( 300 ) ) . await ; } self . shutdown ( None ) . await ? ; } Ok ( ( ) ) }
Listens for signals from the operating system that the server should
shut down and attempts to gracefully shut down.
Listens for signals from the operating system that the server should shut down and attempts to gracefully shut down .
&self
&self