1
1
mirror of https://github.com/wez/wezterm.git synced 2024-11-13 07:22:52 +03:00

wezterm: break out of pty reader loop when pane is removed

If a pane is killed via mux manipulation, the reader didn't have
a way to notice this and could keep reading the data in a loop.

This commit adds an atomic boolean to signal back from the mux
to the reader.

This isn't perfect; the reader thread may still be blocked in
read until the underlying process is really killed.
This commit is contained in:
Wez Furlong 2020-09-27 18:38:48 -07:00
parent c5efd94bb8
commit b744d986af

View File

@ -11,7 +11,7 @@ use std::cell::{Ref, RefCell, RefMut};
use std::collections::HashMap;
use std::io::Read;
use std::rc::Rc;
use std::sync::atomic::{AtomicUsize, Ordering};
use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering};
use std::sync::Arc;
use std::thread;
use thiserror::*;
@ -45,8 +45,9 @@ fn read_from_pane_pty(pane_id: PaneId, mut reader: Box<dyn std::io::Read>) {
let mut buf = [0; BUFSIZE];
let mut lim = RateLimiter::new(|config| config.ratelimit_output_bytes_per_second);
let dead = Arc::new(AtomicBool::new(false));
loop {
'outer: while !dead.load(Ordering::Relaxed) {
match reader.read(&mut buf) {
Ok(size) if size == 0 => {
error!("read_pty EOF: pane_id {}", pane_id);
@ -61,16 +62,27 @@ fn read_from_pane_pty(pane_id: PaneId, mut reader: Box<dyn std::io::Read>) {
let mut pos = 0;
while pos < size {
if dead.load(Ordering::Relaxed) {
break 'outer;
}
match lim.admit_check((size - pos) as u32) {
Ok(len) => {
let len = len as usize;
let data = buf[pos..pos + len].to_vec();
pos += len;
promise::spawn::spawn_into_main_thread_with_low_priority(async move {
let mux = Mux::get().unwrap();
if let Some(pane) = mux.get_pane(pane_id) {
pane.advance_bytes(&data);
mux.notify(MuxNotification::PaneOutput(pane_id));
promise::spawn::spawn_into_main_thread_with_low_priority({
let dead = Arc::clone(&dead);
async move {
let mux = Mux::get().unwrap();
if let Some(pane) = mux.get_pane(pane_id) {
pane.advance_bytes(&data);
mux.notify(MuxNotification::PaneOutput(pane_id));
} else {
// Something else removed the pane from
// the mux, so we should stop trying to
// process it.
dead.store(true, Ordering::Relaxed);
}
}
});
}