1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
use lazy_static::lazy_static;
use nix::sys::signal::{pthread_sigmask, sigaction};
use nix::sys::signal::{SaFlags, SigAction, SigHandler, SigSet, SigmaskHow, Signal};
use std::collections::HashMap;
use std::sync::atomic::{AtomicUsize, Ordering};
use std::sync::mpsc::{channel, Receiver, Sender};
use std::sync::Mutex;
use std::sync::Once;
use std::thread;
lazy_static! {
static ref NOTIFIER_COUNTER: AtomicUsize = AtomicUsize::new(0);
static ref NOTIFIER: Mutex<HashMap<usize, Sender<()>>> = Mutex::new(HashMap::new());
}
static ONCE: Once = Once::new();
pub fn initialize_signals() {
ONCE.call_once(listen_sigwinch);
}
pub fn notify_on_sigwinch() -> (usize, Receiver<()>) {
let (tx, rx) = channel();
let new_id = NOTIFIER_COUNTER.fetch_add(1, Ordering::Relaxed);
let mut notifiers = NOTIFIER.lock().unwrap();
notifiers.entry(new_id).or_insert(tx);
(new_id, rx)
}
pub fn unregister_sigwinch(id: usize) {
let mut notifiers = NOTIFIER.lock().unwrap();
notifiers.remove(&id);
}
extern "C" fn handle_sigwiwnch(_: i32) {}
fn listen_sigwinch() {
let (tx_sig, rx_sig) = channel();
let mut sigset = SigSet::empty();
sigset.add(Signal::SIGWINCH);
let _ = pthread_sigmask(SigmaskHow::SIG_BLOCK, Some(&sigset), None);
let action = SigAction::new(
SigHandler::Handler(handle_sigwiwnch),
SaFlags::empty(),
SigSet::empty(),
);
unsafe {
let _ = sigaction(Signal::SIGWINCH, &action);
}
thread::spawn(move || {
loop {
let _errno = sigset.wait();
let _ = tx_sig.send(());
}
});
thread::spawn(move || {
while let Ok(_) = rx_sig.recv() {
let notifiers = NOTIFIER.lock().unwrap();
for (_, sender) in notifiers.iter() {
let _ = sender.send(());
}
}
});
}