signal_handler/
register.rs

1use core::ops::{Deref, DerefMut};
2use std::{collections::HashMap, io::Error as IoError};
3
4use channel_sender::{generic::Sender, SendError};
5use signal_hook::{
6    consts::signal::*,
7    low_level::{register, unregister},
8    SigId,
9};
10
11//
12pub type SignalNumber = i32;
13
14//
15#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
16pub enum RegisterType {
17    #[cfg(not(windows))]
18    ReloadConfig,
19    WaitForStop,
20    #[cfg(not(windows))]
21    PrintStats,
22}
23
24impl RegisterType {
25    pub fn signal_numbers(&self) -> Vec<SignalNumber> {
26        match self {
27            #[cfg(not(windows))]
28            RegisterType::ReloadConfig => {
29                vec![SIGHUP]
30            }
31            RegisterType::WaitForStop => {
32                let mut list = vec![SIGINT, SIGTERM];
33                #[cfg(not(windows))]
34                {
35                    list.push(SIGQUIT);
36                }
37                list
38            }
39            #[cfg(not(windows))]
40            RegisterType::PrintStats => {
41                vec![SIGUSR1]
42            }
43        }
44    }
45}
46
47//
48#[derive(Debug, Clone, Default)]
49pub struct Registers(HashMap<RegisterType, Vec<SignalNumber>>);
50
51impl Deref for Registers {
52    type Target = HashMap<RegisterType, Vec<SignalNumber>>;
53
54    fn deref(&self) -> &Self::Target {
55        &self.0
56    }
57}
58
59impl DerefMut for Registers {
60    fn deref_mut(&mut self) -> &mut Self::Target {
61        &mut self.0
62    }
63}
64
65//
66impl Registers {
67    pub fn new() -> Self {
68        Self::default()
69    }
70
71    #[cfg(not(windows))]
72    pub fn insert_reload_config(&mut self) -> Option<Vec<SignalNumber>> {
73        self.insert(
74            RegisterType::ReloadConfig,
75            RegisterType::ReloadConfig.signal_numbers(),
76        )
77    }
78
79    pub fn insert_wait_for_stop(&mut self) -> Option<Vec<SignalNumber>> {
80        self.insert(
81            RegisterType::WaitForStop,
82            RegisterType::WaitForStop.signal_numbers(),
83        )
84    }
85
86    #[cfg(not(windows))]
87    pub fn insert_print_stats(&mut self) -> Option<Vec<SignalNumber>> {
88        self.insert(
89            RegisterType::PrintStats,
90            RegisterType::PrintStats.signal_numbers(),
91        )
92    }
93}
94
95//
96pub type RegisterError = IoError;
97
98impl Registers {
99    pub fn register<Tx>(self, sender: Tx) -> Result<HashMap<SignalNumber, SigId>, RegisterError>
100    where
101        Tx: Sender<RegisterType> + Clone + Send + Sync + 'static,
102    {
103        let mut map = HashMap::new();
104
105        for (tp, signal_numbers) in &self.0 {
106            for signal_number in signal_numbers {
107                let sender = sender.clone();
108
109                let signal_number = *signal_number;
110                let tp = *tp;
111
112                let sig_id = unsafe {
113                    register(signal_number, move || {
114                        match sender.send(tp) {
115                            Ok(_) => {}
116                            Err(SendError::Full(_)) => {
117                                // ignore
118                            }
119                            Err(SendError::Closed(_)) | Err(SendError::Disconnected(_)) => {
120                                // ignore
121                            }
122                        }
123                    })
124                }?;
125
126                map.insert(signal_number, sig_id);
127            }
128        }
129
130        Ok(map)
131    }
132
133    pub fn unregister(sig_ids: &[SigId]) {
134        for sig_id in sig_ids {
135            unregister(*sig_id);
136        }
137    }
138}