forked from romanz/electrs
-
Notifications
You must be signed in to change notification settings - Fork 166
Expand file tree
/
Copy pathsignal.rs
More file actions
75 lines (68 loc) · 2.53 KB
/
signal.rs
File metadata and controls
75 lines (68 loc) · 2.53 KB
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
73
74
75
use crossbeam_channel::{self as channel, after, select};
use std::thread;
use std::time::{Duration, Instant};
use signal_hook::consts::{SIGINT, SIGTERM, SIGUSR1};
use crate::errors::*;
use crate::new_index::zmq::ZmqEvent;
#[derive(Clone)] // so multiple threads could wait on signals
pub struct Waiter {
receiver: channel::Receiver<i32>,
zmq_receiver: channel::Receiver<ZmqEvent>,
}
fn notify(signals: &[i32]) -> channel::Receiver<i32> {
let (s, r) = channel::bounded(1);
let mut signals =
signal_hook::iterator::Signals::new(signals).expect("failed to register signal hook");
thread::spawn(move || {
for signal in signals.forever() {
s.send(signal)
.unwrap_or_else(|_| panic!("failed to send signal {}", signal));
}
});
r
}
impl Waiter {
pub fn start(zmq_event_receive: channel::Receiver<ZmqEvent>) -> Waiter {
Waiter {
receiver: notify(&[
SIGINT, SIGTERM,
SIGUSR1, // allow external triggering (e.g. via bitcoind `blocknotify`)
]),
zmq_receiver: zmq_event_receive,
}
}
pub fn wait(&self, duration: Duration, accept_block_notification: bool) -> Result<()> {
let start = Instant::now();
select! {
recv(self.receiver) -> msg => {
match msg {
Ok(sig) if sig == SIGUSR1 => {
trace!("notified via SIGUSR1");
if accept_block_notification {
Ok(())
} else {
let wait_more = duration.saturating_sub(start.elapsed());
self.wait(wait_more, accept_block_notification)
}
}
Ok(sig) => bail!(ErrorKind::Interrupt(sig)),
Err(_) => bail!("signal hook channel disconnected"),
}
},
recv(self.zmq_receiver) -> msg => {
match msg {
Ok(_) => {
if accept_block_notification {
Ok(())
} else {
let wait_more = duration.saturating_sub(start.elapsed());
self.wait(wait_more, accept_block_notification)
}
}
Err(_) => bail!("signal hook channel disconnected"),
}
},
recv(after(duration)) -> _ => Ok(()),
}
}
}