brk_exit/
lib.rs

1#![doc = include_str!("../README.md")]
2
3use std::{
4    process::exit,
5    sync::{
6        Arc,
7        atomic::{AtomicBool, Ordering},
8    },
9    thread::sleep,
10    time::Duration,
11};
12
13use log::info;
14
15#[derive(Default, Clone)]
16pub struct Exit {
17    blocking: Arc<AtomicBool>,
18    triggered: Arc<AtomicBool>,
19}
20
21impl Exit {
22    pub fn new() -> Self {
23        let s = Self {
24            triggered: Arc::new(AtomicBool::new(false)),
25            blocking: Arc::new(AtomicBool::new(false)),
26        };
27
28        let triggered = s.triggered.clone();
29
30        let blocking = s.blocking.clone();
31        let is_blocking = move || blocking.load(Ordering::SeqCst);
32
33        ctrlc::set_handler(move || {
34            info!("Exitting...");
35
36            triggered.store(true, Ordering::SeqCst);
37
38            if is_blocking() {
39                info!("Waiting to exit safely...");
40
41                while is_blocking() {
42                    sleep(Duration::from_millis(50));
43                }
44            }
45
46            exit(0);
47        })
48        .expect("Error setting Ctrl-C handler");
49
50        s
51    }
52
53    pub fn block(&self) {
54        self.blocking.store(true, Ordering::SeqCst);
55    }
56
57    pub fn release(&self) {
58        self.blocking.store(false, Ordering::SeqCst);
59    }
60
61    pub fn triggered(&self) -> bool {
62        self.triggered.load(Ordering::SeqCst)
63    }
64}