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
98 #[test]
99 fn cancelado_retorna_false_antes_de_sinal() {
100 let _ = cancelado();
104 }
105
106 #[test]
107 fn obter_flag_retorna_mesmo_arc() {
108 let flag_a = obter_flag();
109 let flag_b = obter_flag();
110 assert!(Arc::ptr_eq(&flag_a, &flag_b));
112 }
113
114 #[test]
115 fn flag_pode_ser_marcada_e_lida() {
116 let flag = obter_flag();
117 let valor_anterior = flag.load(Ordering::SeqCst);
119 flag.store(valor_anterior, Ordering::SeqCst);
120 assert_eq!(flag.load(Ordering::SeqCst), valor_anterior);
121 }
122
123 #[test]
124 fn terminado_false_por_padrao() {
125 let flag = obter_flag_sigterm();
128 flag.store(false, Ordering::SeqCst);
129 assert!(!terminado());
130 }
131
132 #[test]
133 fn obter_flag_sigterm_retorna_mesmo_arc() {
134 let a = obter_flag_sigterm();
135 let b = obter_flag_sigterm();
136 assert!(Arc::ptr_eq(&a, &b));
137 }
138
139 #[test]
140 fn terminado_verdadeiro_apos_set() {
141 let flag = obter_flag_sigterm();
142 flag.store(true, Ordering::SeqCst);
143 assert!(terminado());
144 flag.store(false, Ordering::SeqCst); }
146
147 #[test]
148 fn cancelado_false_apos_reset() {
149 let flag = obter_flag();
150 flag.store(true, Ordering::SeqCst);
151 assert!(cancelado());
152 flag.store(false, Ordering::SeqCst);
153 assert!(!cancelado());
154 }
155}