1use anyhow::Result;
8use std::sync::atomic::{AtomicBool, Ordering};
9use std::sync::{Arc, OnceLock};
10
11static FLAG_CANCELAMENTO: OnceLock<Arc<AtomicBool>> = OnceLock::new();
13
14pub fn registrar_handler() -> Result<()> {
19 let flag = obter_flag();
20 let flag_clone = Arc::clone(&flag);
21
22 ctrlc::set_handler(move || {
23 flag_clone.store(true, Ordering::SeqCst);
24 tracing::debug!("sinal de cancelamento recebido via Ctrl+C");
25 })?;
26
27 tracing::debug!("handler de Ctrl+C registrado com sucesso");
28
29 #[cfg(unix)]
30 {
31 let flag_term = obter_flag_sigterm();
32 signal_hook::flag::register(signal_hook::consts::SIGTERM, flag_term)?;
33 tracing::debug!("handler SIGTERM registrado");
34 }
35
36 #[cfg(not(unix))]
37 {
38 let _ = obter_flag_sigterm(); }
42
43 Ok(())
44}
45
46#[must_use]
60pub fn cancelado() -> bool {
61 FLAG_CANCELAMENTO
62 .get()
63 .map(|f| f.load(Ordering::SeqCst))
64 .unwrap_or(false)
65}
66
67#[must_use]
72pub fn obter_flag() -> Arc<AtomicBool> {
73 Arc::clone(FLAG_CANCELAMENTO.get_or_init(|| Arc::new(AtomicBool::new(false))))
74}
75
76static FLAG_SIGTERM: OnceLock<Arc<AtomicBool>> = OnceLock::new();
78
79#[must_use]
81pub fn terminado() -> bool {
82 FLAG_SIGTERM
83 .get()
84 .map(|f| f.load(Ordering::SeqCst))
85 .unwrap_or(false)
86}
87
88#[must_use]
90pub fn obter_flag_sigterm() -> Arc<AtomicBool> {
91 Arc::clone(FLAG_SIGTERM.get_or_init(|| Arc::new(AtomicBool::new(false))))
92}
93
94#[cfg(test)]
95mod testes {
96 use super::*;
97 use serial_test::serial;
98
99 #[test]
100 #[serial]
101 fn cancelado_retorna_false_antes_de_sinal() {
102 let _ = cancelado();
106 }
107
108 #[test]
109 #[serial]
110 fn obter_flag_retorna_mesmo_arc() {
111 let flag_a = obter_flag();
112 let flag_b = obter_flag();
113 assert!(Arc::ptr_eq(&flag_a, &flag_b));
115 }
116
117 #[test]
118 #[serial]
119 fn flag_pode_ser_marcada_e_lida() {
120 let flag = obter_flag();
121 let valor_anterior = flag.load(Ordering::SeqCst);
123 flag.store(valor_anterior, Ordering::SeqCst);
124 assert_eq!(flag.load(Ordering::SeqCst), valor_anterior);
125 }
126
127 #[test]
128 #[serial]
129 fn terminado_false_por_padrao() {
130 let flag = obter_flag_sigterm();
132 flag.store(false, Ordering::SeqCst);
133 assert!(!terminado());
134 }
135
136 #[test]
137 #[serial]
138 fn obter_flag_sigterm_retorna_mesmo_arc() {
139 let a = obter_flag_sigterm();
140 let b = obter_flag_sigterm();
141 assert!(Arc::ptr_eq(&a, &b));
142 }
143
144 #[test]
145 #[serial]
146 fn terminado_verdadeiro_apos_set() {
147 let flag = obter_flag_sigterm();
148 flag.store(true, Ordering::SeqCst);
149 assert!(terminado());
150 flag.store(false, Ordering::SeqCst); }
152
153 #[test]
154 #[serial]
155 fn cancelado_false_apos_reset() {
156 let flag = obter_flag();
157 flag.store(true, Ordering::SeqCst);
158 assert!(cancelado());
159 flag.store(false, Ordering::SeqCst);
160 assert!(!cancelado());
161 }
162}