will_exit/
lib.rs

1#![cfg_attr(docsrs, feature(doc_cfg))]
2
3use core::time::Duration;
4use std::sync::atomic::{AtomicBool, AtomicU16, Ordering};
5use std::{io, process, thread};
6
7static INITED: AtomicBool = AtomicBool::new(false);
8static EXITING: AtomicBool = AtomicBool::new(false);
9static EXIT_TIME: AtomicU16 = AtomicU16::new(0);
10#[cfg(feature = "async")]
11static EVENT: event_listener::Event = event_listener::Event::new();
12
13pub fn exit(code: i32) -> ! {
14    EXITING.store(true, Ordering::SeqCst);
15    #[cfg(feature = "async")]
16    EVENT.notify(usize::MAX);
17
18    let exit_time = EXIT_TIME.load(Ordering::SeqCst);
19    thread::sleep(Duration::from_millis(exit_time as u64));
20    process::exit(code);
21}
22pub fn send_exit_signal(code: i32) {
23    thread::Builder::new()
24        .name("will_exit".to_string())
25        .spawn(move || exit(code))
26        .unwrap();
27}
28
29pub fn will_exit() -> bool {
30    EXITING.load(Ordering::Acquire)
31}
32#[cfg(feature = "async")]
33#[cfg_attr(docsrs, doc(cfg(feature = "async")))]
34pub async fn wait_will_exit() {
35    while EXITING.load(Ordering::Acquire) == false {
36        EVENT.listen().await
37    }
38}
39
40/// 设置调用exit()后多少毫秒后退出程序
41pub fn init(exit_time: u16) -> Result<(), io::Error> {
42    EXIT_TIME.store(exit_time, Ordering::SeqCst);
43    let result = INITED.compare_exchange(false, true, Ordering::AcqRel, Ordering::Acquire);
44    if result.is_ok() {
45        unsafe {
46            signal_hook_registry::register(libc::SIGINT, || send_exit_signal(libc::SIGINT))?;
47            signal_hook_registry::register(libc::SIGTERM, || send_exit_signal(libc::SIGTERM))?;
48            signal_hook_registry::register(libc::SIGABRT, || send_exit_signal(libc::SIGABRT))?;
49            #[cfg(not(windows))]
50            signal_hook_registry::register(libc::SIGQUIT, || send_exit_signal(libc::SIGQUIT))?;
51        }
52    }
53    Ok(())
54}