input_thread: add atomic refcount to check if thread is dead
parent
0882dbbad0
commit
44ffbe54e2
39
src/state.rs
39
src/state.rs
|
@ -51,16 +51,22 @@ struct InputHandler {
|
||||||
pipe: (RawFd, RawFd),
|
pipe: (RawFd, RawFd),
|
||||||
rx: Receiver<InputCommand>,
|
rx: Receiver<InputCommand>,
|
||||||
tx: Sender<InputCommand>,
|
tx: Sender<InputCommand>,
|
||||||
|
state_tx: Sender<ThreadEvent>,
|
||||||
|
control: std::sync::Weak<()>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl InputHandler {
|
impl InputHandler {
|
||||||
fn restore(&self, tx: Sender<ThreadEvent>) {
|
fn restore(&mut self) {
|
||||||
|
let working = Arc::new(());
|
||||||
|
let control = Arc::downgrade(&working);
|
||||||
|
|
||||||
/* Clear channel without blocking. switch_to_main_screen() issues a kill when
|
/* Clear channel without blocking. switch_to_main_screen() issues a kill when
|
||||||
* returning from a fork and there's no input thread, so the newly created thread will
|
* returning from a fork and there's no input thread, so the newly created thread will
|
||||||
* receive it and die. */
|
* receive it and die. */
|
||||||
//let _ = self.rx.try_iter().count();
|
//let _ = self.rx.try_iter().count();
|
||||||
let rx = self.rx.clone();
|
let rx = self.rx.clone();
|
||||||
let pipe = self.pipe.0;
|
let pipe = self.pipe.0;
|
||||||
|
let tx = self.state_tx.clone();
|
||||||
thread::Builder::new()
|
thread::Builder::new()
|
||||||
.name("input-thread".to_string())
|
.name("input-thread".to_string())
|
||||||
.spawn(move || {
|
.spawn(move || {
|
||||||
|
@ -70,15 +76,27 @@ impl InputHandler {
|
||||||
},
|
},
|
||||||
&rx,
|
&rx,
|
||||||
pipe,
|
pipe,
|
||||||
|
working,
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
self.control = control;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn kill(&self) {
|
fn kill(&self) {
|
||||||
let _ = nix::unistd::write(self.pipe.1, &[1]);
|
let _ = nix::unistd::write(self.pipe.1, &[1]);
|
||||||
self.tx.send(InputCommand::Kill).unwrap();
|
self.tx.send(InputCommand::Kill).unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn check(&mut self) {
|
||||||
|
match self.control.upgrade() {
|
||||||
|
Some(_) => {}
|
||||||
|
None => {
|
||||||
|
debug!("restarting input_thread");
|
||||||
|
self.restore();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A context container for loaded settings, accounts, UI changes, etc.
|
/// A context container for loaded settings, accounts, UI changes, etc.
|
||||||
|
@ -95,7 +113,7 @@ pub struct Context {
|
||||||
pub replies: VecDeque<UIEvent>,
|
pub replies: VecDeque<UIEvent>,
|
||||||
sender: Sender<ThreadEvent>,
|
sender: Sender<ThreadEvent>,
|
||||||
receiver: Receiver<ThreadEvent>,
|
receiver: Receiver<ThreadEvent>,
|
||||||
input: InputHandler,
|
input_thread: InputHandler,
|
||||||
work_controller: WorkController,
|
work_controller: WorkController,
|
||||||
job_executor: Arc<JobExecutor>,
|
job_executor: Arc<JobExecutor>,
|
||||||
pub children: Vec<std::process::Child>,
|
pub children: Vec<std::process::Child>,
|
||||||
|
@ -110,11 +128,11 @@ impl Context {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn input_kill(&self) {
|
pub fn input_kill(&self) {
|
||||||
self.input.kill();
|
self.input_thread.kill();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn restore_input(&self) {
|
pub fn restore_input(&mut self) {
|
||||||
self.input.restore(self.sender.clone());
|
self.input_thread.restore();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_online(&mut self, account_pos: usize) -> Result<()> {
|
pub fn is_online(&mut self, account_pos: usize) -> Result<()> {
|
||||||
|
@ -299,6 +317,8 @@ impl State {
|
||||||
|
|
||||||
timer.thread().unpark();
|
timer.thread().unpark();
|
||||||
|
|
||||||
|
let working = Arc::new(());
|
||||||
|
let control = Arc::downgrade(&working);
|
||||||
let mut s = State {
|
let mut s = State {
|
||||||
cols,
|
cols,
|
||||||
rows,
|
rows,
|
||||||
|
@ -334,13 +354,15 @@ impl State {
|
||||||
children: vec![],
|
children: vec![],
|
||||||
plugin_manager,
|
plugin_manager,
|
||||||
|
|
||||||
sender,
|
input_thread: InputHandler {
|
||||||
receiver,
|
|
||||||
input: InputHandler {
|
|
||||||
pipe: input_thread_pipe,
|
pipe: input_thread_pipe,
|
||||||
rx: input_thread.1,
|
rx: input_thread.1,
|
||||||
tx: input_thread.0,
|
tx: input_thread.0,
|
||||||
|
control,
|
||||||
|
state_tx: sender.clone(),
|
||||||
},
|
},
|
||||||
|
sender,
|
||||||
|
receiver,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
s.draw_rate_limit
|
s.draw_rate_limit
|
||||||
|
@ -1128,5 +1150,6 @@ impl State {
|
||||||
if ctr != self.context.accounts.len() {
|
if ctr != self.context.accounts.len() {
|
||||||
self.timer.thread().unpark();
|
self.timer.thread().unpark();
|
||||||
}
|
}
|
||||||
|
self.context.input_thread.check();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -163,6 +163,7 @@ pub fn get_events(
|
||||||
mut closure: impl FnMut((Key, Vec<u8>)),
|
mut closure: impl FnMut((Key, Vec<u8>)),
|
||||||
rx: &Receiver<InputCommand>,
|
rx: &Receiver<InputCommand>,
|
||||||
new_command_fd: RawFd,
|
new_command_fd: RawFd,
|
||||||
|
working: std::sync::Arc<()>,
|
||||||
) {
|
) {
|
||||||
let stdin = std::io::stdin();
|
let stdin = std::io::stdin();
|
||||||
let stdin_fd = PollFd::new(std::io::stdin().as_raw_fd(), PollFlags::POLLIN);
|
let stdin_fd = PollFd::new(std::io::stdin().as_raw_fd(), PollFlags::POLLIN);
|
||||||
|
@ -229,6 +230,7 @@ pub fn get_events(
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
drop(working);
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'de> Deserialize<'de> for Key {
|
impl<'de> Deserialize<'de> for Key {
|
||||||
|
|
Loading…
Reference in New Issue