Send timer ID as si_value to SIGALRM handler

Associate each alarm signal with the timer of its origin.
async
Manos Pitsidianakis 2020-01-08 17:07:14 +02:00
parent a365a846b8
commit 5e912db461
Signed by: Manos Pitsidianakis
GPG Key ID: 73627C2F690DF710
6 changed files with 71 additions and 26 deletions

13
Cargo.lock generated
View File

@ -746,7 +746,8 @@ dependencies = [
"crossbeam 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", "crossbeam 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
"melib 0.4.1", "melib 0.4.1",
"nix 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)", "nix 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)",
"signal-hook 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", "signal-hook 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)",
"signal-hook-registry 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"ui 0.4.1", "ui 0.4.1",
"xdg 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "xdg 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
@ -1523,16 +1524,16 @@ dependencies = [
[[package]] [[package]]
name = "signal-hook" name = "signal-hook"
version = "0.1.10" version = "0.1.12"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ dependencies = [
"libc 0.2.64 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.64 (registry+https://github.com/rust-lang/crates.io-index)",
"signal-hook-registry 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "signal-hook-registry 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]] [[package]]
name = "signal-hook-registry" name = "signal-hook-registry"
version = "1.1.1" version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ dependencies = [
"arc-swap 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "arc-swap 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
@ -2299,8 +2300,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
"checksum serde_derive 1.0.92 (registry+https://github.com/rust-lang/crates.io-index)" = "46a3223d0c9ba936b61c0d2e3e559e3217dbfb8d65d06d26e8b3c25de38bae3e" "checksum serde_derive 1.0.92 (registry+https://github.com/rust-lang/crates.io-index)" = "46a3223d0c9ba936b61c0d2e3e559e3217dbfb8d65d06d26e8b3c25de38bae3e"
"checksum serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)" = "5a23aa71d4a4d43fdbfaac00eff68ba8a06a51759a89ac3304323e800c4dd40d" "checksum serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)" = "5a23aa71d4a4d43fdbfaac00eff68ba8a06a51759a89ac3304323e800c4dd40d"
"checksum serde_urlencoded 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9ec5d77e2d4c73717816afac02670d5c4f534ea95ed430442cad02e7a6e32c97" "checksum serde_urlencoded 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9ec5d77e2d4c73717816afac02670d5c4f534ea95ed430442cad02e7a6e32c97"
"checksum signal-hook 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "4f61c4d59f3aaa9f61bba6450a9b80ba48362fd7d651689e7a10c453b1f6dc68" "checksum signal-hook 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "7a9c17dd3ba2d36023a5c9472ecddeda07e27fd0b05436e8c1e0c8f178185652"
"checksum signal-hook-registry 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1797d48f38f91643908bb14e35e79928f9f4b3cefb2420a564dde0991b4358dc" "checksum signal-hook-registry 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "94f478ede9f64724c5d173d7bb56099ec3e2d9fc2774aac65d34b8b890405f41"
"checksum slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8" "checksum slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8"
"checksum smallvec 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)" = "f7b0758c52e15a8b5e3691eae6cc559f08eee9406e548a4477ba4e67770a82b6" "checksum smallvec 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)" = "f7b0758c52e15a8b5e3691eae6cc559f08eee9406e548a4477ba4e67770a82b6"
"checksum smallvec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "44e59e0c9fa00817912ae6e4e6e3c4fe04455e75699d06eedc7d85917ed8e8f4" "checksum smallvec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "44e59e0c9fa00817912ae6e4e6e3c4fe04455e75699d06eedc7d85917ed8e8f4"

View File

@ -11,7 +11,8 @@ path = "src/bin.rs"
[dependencies] [dependencies]
xdg = "2.1.0" xdg = "2.1.0"
crossbeam = "0.7.2" crossbeam = "0.7.2"
signal-hook = "0.1.10" signal-hook = "0.1.12"
signal-hook-registry = "1.2.0"
nix = "*" nix = "*"
melib = { path = "melib", version = "*" } melib = { path = "melib", version = "*" }
ui = { path = "ui", version = "*" } ui = { path = "ui", version = "*" }

View File

@ -42,12 +42,23 @@ use ui::*;
use nix; use nix;
use std::os::raw::c_int; use std::os::raw::c_int;
use xdg; use xdg;
fn notify( fn notify(
signals: &[c_int], signals: &[c_int],
sender: crossbeam::channel::Sender<ThreadEvent>, sender: crossbeam::channel::Sender<ThreadEvent>,
) -> std::result::Result<crossbeam::channel::Receiver<c_int>, std::io::Error> { ) -> std::result::Result<crossbeam::channel::Receiver<c_int>, std::io::Error> {
let alarm_sender = sender.clone();
let alarm_handler = move |info: &nix::libc::siginfo_t| {
let value = unsafe { info.si_value().sival_ptr as u8 };
alarm_sender
.send(ThreadEvent::UIEvent(UIEvent::Timer(value)))
.unwrap();
};
unsafe {
signal_hook_registry::register_sigaction(signal_hook::SIGALRM, alarm_handler)?;
}
let (s, r) = crossbeam::channel::bounded(100); let (s, r) = crossbeam::channel::bounded(100);
let signals = signal_hook::iterator::Signals::new(signals)?; let signals = signal_hook::iterator::Signals::new(signals)?;
std::thread::spawn(move || { std::thread::spawn(move || {
@ -218,22 +229,21 @@ fn run_app() -> Result<()> {
std::env::set_var("MELI_CONFIG", config_location); std::env::set_var("MELI_CONFIG", config_location);
} }
/* Create the application State. */ /* Create a channel to communicate with other threads. The main process is the sole receiver.
let mut state = State::new()?; * */
let (sender, receiver) = crossbeam::channel::bounded(32 * ::std::mem::size_of::<ThreadEvent>());
let receiver = state.receiver();
let sender = state.sender();
/* Catch SIGWINCH to handle terminal resizing */ /* Catch SIGWINCH to handle terminal resizing */
let signals = &[ let signals = &[
signal_hook::SIGALRM,
/* Catch SIGWINCH to handle terminal resizing */ /* Catch SIGWINCH to handle terminal resizing */
signal_hook::SIGWINCH, signal_hook::SIGWINCH,
/* Catch SIGCHLD to handle embed applications status change */ /* Catch SIGCHLD to handle embed applications status change */
signal_hook::SIGCHLD, signal_hook::SIGCHLD,
]; ];
let signal_recvr = notify(signals, sender)?; let signal_recvr = notify(signals, sender.clone())?;
/* Create the application State. */
let mut state = State::new(sender, receiver.clone())?;
let window = Box::new(Tabbed::new(vec![ let window = Box::new(Tabbed::new(vec![
Box::new(listing::Listing::new(&state.context.accounts)), Box::new(listing::Listing::new(&state.context.accounts)),
@ -388,10 +398,6 @@ fn run_app() -> Result<()> {
state.redraw(); state.redraw();
} }
}, },
signal_hook::SIGALRM => {
state.rcv_event(UIEvent::Timer);
state.redraw();
},
other => { other => {
debug!("got other signal: {:?}", other); debug!("got other signal: {:?}", other);
} }

View File

@ -191,9 +191,12 @@ pub mod timer {
use libc::sigevent; use libc::sigevent;
use libc::{itimerspec, timespec}; use libc::{itimerspec, timespec};
use nix::sys::signal::{SigEvent, SigevNotify}; use nix::sys::signal::{SigEvent, SigevNotify};
use std::cell::RefCell;
use std::convert::TryInto; use std::convert::TryInto;
use std::time::Duration; use std::time::Duration;
thread_local!(static TIMER_IDS: RefCell<u8> = RefCell::new(0));
#[allow(non_camel_case_types)] #[allow(non_camel_case_types)]
pub type timer_t = libc::intptr_t; pub type timer_t = libc::intptr_t;
@ -215,6 +218,7 @@ pub mod timer {
timer_id: timer_t, timer_id: timer_t,
interval: Duration, interval: Duration,
value: Duration, value: Duration,
pub si_value: u8,
} }
impl Drop for PosixTimer { impl Drop for PosixTimer {
@ -255,6 +259,35 @@ pub mod timer {
} }
} }
pub fn set_value(&mut self, value: Duration) {
let spec = itimerspec {
it_interval: timespec {
tv_sec: self.interval.as_secs().try_into().unwrap_or(0),
tv_nsec: self.interval.subsec_nanos().try_into().unwrap_or(0),
},
it_value: timespec {
tv_sec: value.as_secs().try_into().unwrap_or(0),
tv_nsec: value.subsec_nanos().try_into().unwrap_or(0),
},
};
let ret =
unsafe { timer_settime(self.timer_id, 0, &spec as *const _, std::ptr::null_mut()) };
if ret != 0 {
match ret {
libc::EFAULT => {
panic!(
"EFAULT: new_value, old_value, or curr_value is not a valid pointer."
);
}
libc::EINVAL => {
panic!("EINVAL: timerid is invalid.");
}
_ => {}
}
}
self.value = value;
}
pub fn set_interval(&mut self, interval: Duration) { pub fn set_interval(&mut self, interval: Duration) {
let spec = itimerspec { let spec = itimerspec {
it_interval: timespec { it_interval: timespec {
@ -320,9 +353,15 @@ pub mod timer {
) -> Result<PosixTimer> { ) -> Result<PosixTimer> {
let mut timer_id = Default::default(); let mut timer_id = Default::default();
let mut si_value = 0;
TIMER_IDS.with(|t| {
si_value = *t.borrow_mut();
*t.borrow_mut() += 1;
});
let sigev_notify = SigevNotify::SigevSignal { let sigev_notify = SigevNotify::SigevSignal {
signal, signal,
si_value: 0, si_value: si_value as isize,
}; };
let event = SigEvent::new(sigev_notify); let event = SigEvent::new(sigev_notify);
@ -382,6 +421,7 @@ pub mod timer {
timer_id, timer_id,
interval, interval,
value, value,
si_value,
}) })
} }
} }

View File

@ -32,7 +32,7 @@ use super::*;
use crate::plugins::PluginManager; use crate::plugins::PluginManager;
use melib::backends::{FolderHash, NotifyFn}; use melib::backends::{FolderHash, NotifyFn};
use crossbeam::channel::{bounded, unbounded, Receiver, Sender}; use crossbeam::channel::{unbounded, Receiver, Sender};
use fnv::FnvHashMap; use fnv::FnvHashMap;
use std::env; use std::env;
use std::io::Write; use std::io::Write;
@ -199,11 +199,7 @@ impl Drop for State {
} }
impl State { impl State {
pub fn new() -> Result<Self> { pub fn new(sender: Sender<ThreadEvent>, receiver: Receiver<ThreadEvent>) -> Result<Self> {
/* Create a channel to communicate with other threads. The main process is the sole receiver.
* */
let (sender, receiver) = bounded(32 * ::std::mem::size_of::<ThreadEvent>());
/* /*
* Create async channel to block the input-thread if we need to fork and stop it from reading * Create async channel to block the input-thread if we need to fork and stop it from reading
* stdin, see get_events() for details * stdin, see get_events() for details

View File

@ -106,6 +106,7 @@ pub enum UIEvent {
EnvelopeUpdate(EnvelopeHash), EnvelopeUpdate(EnvelopeHash),
EnvelopeRename(EnvelopeHash, EnvelopeHash), // old_hash, new_hash EnvelopeRename(EnvelopeHash, EnvelopeHash), // old_hash, new_hash
EnvelopeRemove(EnvelopeHash), EnvelopeRemove(EnvelopeHash),
Timer(u8),
} }
impl From<RefreshEvent> for UIEvent { impl From<RefreshEvent> for UIEvent {