aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorAram Drevekenin <aram@poor.dev>2021-01-20 19:25:35 +0100
committerGitHub <noreply@github.com>2021-01-20 19:25:35 +0100
commitdecc38232b7318190f7ce20f9eccff3814bcc68b (patch)
tree39ac308a6cf8befd5ac07037ad88bae9935f4d7e /src
parentfix(compatibility): fix grid glitch edge-case when resizing (#149) (diff)
downloadsl0ppij-decc38232b7318190f7ce20f9eccff3814bcc68b.tar.gz
sl0ppij-decc38232b7318190f7ce20f9eccff3814bcc68b.tar.xz
sl0ppij-decc38232b7318190f7ce20f9eccff3814bcc68b.zip
fix(main): do not hang on exit (#150)
Diffstat (limited to 'src')
-rw-r--r--src/main.rs597
-rw-r--r--src/screen.rs8
2 files changed, 297 insertions, 308 deletions
diff --git a/src/main.rs b/src/main.rs
index 27e97766..a913de16 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -173,7 +173,6 @@ pub enum AppInstruction {
pub fn start(mut os_input: Box<dyn OsApi>, opts: CliArgs) {
let mut app_state = AppState::default();
- let mut active_threads = vec![];
let command_is_executing = CommandIsExecuting::new();
@@ -225,345 +224,334 @@ pub fn start(mut os_input: Box<dyn OsApi>, opts: CliArgs) {
})
});
- active_threads.push(
- thread::Builder::new()
- .name("pty".to_string())
- .spawn({
- let mut command_is_executing = command_is_executing.clone();
- send_pty_instructions.send(PtyInstruction::NewTab).unwrap();
- move || loop {
- let (event, mut err_ctx) = pty_bus
- .receive_pty_instructions
- .recv()
- .expect("failed to receive event on channel");
- err_ctx.add_call(ContextType::Pty(PtyContext::from(&event)));
- pty_bus.send_screen_instructions.update(err_ctx);
- match event {
- PtyInstruction::SpawnTerminal(file_to_open) => {
- let pid = pty_bus.spawn_terminal(file_to_open);
+ let pty_thread = thread::Builder::new()
+ .name("pty".to_string())
+ .spawn({
+ let mut command_is_executing = command_is_executing.clone();
+ send_pty_instructions.send(PtyInstruction::NewTab).unwrap();
+ move || loop {
+ let (event, mut err_ctx) = pty_bus
+ .receive_pty_instructions
+ .recv()
+ .expect("failed to receive event on channel");
+ err_ctx.add_call(ContextType::Pty(PtyContext::from(&event)));
+ pty_bus.send_screen_instructions.update(err_ctx);
+ match event {
+ PtyInstruction::SpawnTerminal(file_to_open) => {
+ let pid = pty_bus.spawn_terminal(file_to_open);
+ pty_bus
+ .send_screen_instructions
+ .send(ScreenInstruction::NewPane(PaneId::Terminal(pid)))
+ .unwrap();
+ }
+ PtyInstruction::SpawnTerminalVertically(file_to_open) => {
+ let pid = pty_bus.spawn_terminal(file_to_open);
+ pty_bus
+ .send_screen_instructions
+ .send(ScreenInstruction::VerticalSplit(PaneId::Terminal(pid)))
+ .unwrap();
+ }
+ PtyInstruction::SpawnTerminalHorizontally(file_to_open) => {
+ let pid = pty_bus.spawn_terminal(file_to_open);
+ pty_bus
+ .send_screen_instructions
+ .send(ScreenInstruction::HorizontalSplit(PaneId::Terminal(pid)))
+ .unwrap();
+ }
+ PtyInstruction::NewTab => {
+ if let Some(layout) = maybe_layout.clone() {
+ pty_bus.spawn_terminals_for_layout(layout);
+ } else {
+ let pid = pty_bus.spawn_terminal(None);
pty_bus
.send_screen_instructions
- .send(ScreenInstruction::NewPane(PaneId::Terminal(pid)))
+ .send(ScreenInstruction::NewTab(pid))
.unwrap();
}
- PtyInstruction::SpawnTerminalVertically(file_to_open) => {
- let pid = pty_bus.spawn_terminal(file_to_open);
- pty_bus
- .send_screen_instructions
- .send(ScreenInstruction::VerticalSplit(PaneId::Terminal(pid)))
- .unwrap();
+ }
+ PtyInstruction::ClosePane(id) => {
+ pty_bus.close_pane(id);
+ command_is_executing.done_closing_pane();
+ }
+ PtyInstruction::CloseTab(ids) => {
+ pty_bus.close_tab(ids);
+ command_is_executing.done_closing_pane();
+ }
+ PtyInstruction::Quit => {
+ break;
+ }
+ }
+ }
+ })
+ .unwrap();
+
+ let screen_thread = thread::Builder::new()
+ .name("screen".to_string())
+ .spawn({
+ let mut command_is_executing = command_is_executing.clone();
+ let os_input = os_input.clone();
+ let send_pty_instructions = send_pty_instructions.clone();
+ let send_plugin_instructions = send_plugin_instructions.clone();
+ let send_app_instructions = send_app_instructions.clone();
+ let max_panes = opts.max_panes;
+
+ move || {
+ let mut screen = Screen::new(
+ receive_screen_instructions,
+ send_pty_instructions,
+ send_plugin_instructions,
+ send_app_instructions,
+ &full_screen_ws,
+ os_input,
+ max_panes,
+ );
+ loop {
+ let (event, mut err_ctx) = screen
+ .receiver
+ .recv()
+ .expect("failed to receive event on channel");
+ err_ctx.add_call(ContextType::Screen(ScreenContext::from(&event)));
+ screen.send_app_instructions.update(err_ctx);
+ screen.send_pty_instructions.update(err_ctx);
+ match event {
+ ScreenInstruction::Pty(pid, vte_event) => {
+ screen
+ .get_active_tab_mut()
+ .unwrap()
+ .handle_pty_event(pid, vte_event);
}
- PtyInstruction::SpawnTerminalHorizontally(file_to_open) => {
- let pid = pty_bus.spawn_terminal(file_to_open);
- pty_bus
- .send_screen_instructions
- .send(ScreenInstruction::HorizontalSplit(PaneId::Terminal(pid)))
- .unwrap();
+ ScreenInstruction::Render => {
+ screen.render();
}
- PtyInstruction::NewTab => {
- if let Some(layout) = maybe_layout.clone() {
- pty_bus.spawn_terminals_for_layout(layout);
- } else {
- let pid = pty_bus.spawn_terminal(None);
- pty_bus
- .send_screen_instructions
- .send(ScreenInstruction::NewTab(pid))
- .unwrap();
- }
+ ScreenInstruction::NewPane(pid) => {
+ screen.get_active_tab_mut().unwrap().new_pane(pid);
+ command_is_executing.done_opening_new_pane();
+ }
+ ScreenInstruction::HorizontalSplit(pid) => {
+ screen.get_active_tab_mut().unwrap().horizontal_split(pid);
+ command_is_executing.done_opening_new_pane();
+ }
+ ScreenInstruction::VerticalSplit(pid) => {
+ screen.get_active_tab_mut().unwrap().vertical_split(pid);
+ command_is_executing.done_opening_new_pane();
+ }
+ ScreenInstruction::WriteCharacter(bytes) => {
+ screen
+ .get_active_tab_mut()
+ .unwrap()
+ .write_to_active_terminal(bytes);
+ }
+ ScreenInstruction::ResizeLeft => {
+ screen.get_active_tab_mut().unwrap().resize_left();
+ }
+ ScreenInstruction::ResizeRight => {
+ screen.get_active_tab_mut().unwrap().resize_right();
+ }
+ ScreenInstruction::ResizeDown => {
+ screen.get_active_tab_mut().unwrap().resize_down();
+ }
+ ScreenInstruction::ResizeUp => {
+ screen.get_active_tab_mut().unwrap().resize_up();
+ }
+ ScreenInstruction::MoveFocus => {
+ screen.get_active_tab_mut().unwrap().move_focus();
+ }
+ ScreenInstruction::MoveFocusLeft => {
+ screen.get_active_tab_mut().unwrap().move_focus_left();
+ }
+ ScreenInstruction::MoveFocusDown => {
+ screen.get_active_tab_mut().unwrap().move_focus_down();
+ }
+ ScreenInstruction::MoveFocusRight => {
+ screen.get_active_tab_mut().unwrap().move_focus_right();
+ }
+ ScreenInstruction::MoveFocusUp => {
+ screen.get_active_tab_mut().unwrap().move_focus_up();
+ }
+ ScreenInstruction::ScrollUp => {
+ screen
+ .get_active_tab_mut()
+ .unwrap()
+ .scroll_active_terminal_up();
+ }
+ ScreenInstruction::ScrollDown => {
+ screen
+ .get_active_tab_mut()
+ .unwrap()
+ .scroll_active_terminal_down();
+ }
+ ScreenInstruction::ClearScroll => {
+ screen
+ .get_active_tab_mut()
+ .unwrap()
+ .clear_active_terminal_scroll();
+ }
+ ScreenInstruction::CloseFocusedPane => {
+ screen.get_active_tab_mut().unwrap().close_focused_pane();
+ screen.render();
+ }
+ ScreenInstruction::SetSelectable(id, selectable) => {
+ screen
+ .get_active_tab_mut()
+ .unwrap()
+ .set_pane_selectable(id, selectable);
+ // FIXME: Is this needed?
+ screen.render();
+ }
+ ScreenInstruction::ClosePane(id) => {
+ screen.get_active_tab_mut().unwrap().close_pane(id);
+ screen.render();
+ }
+ ScreenInstruction::ToggleActiveTerminalFullscreen => {
+ screen
+ .get_active_tab_mut()
+ .unwrap()
+ .toggle_active_pane_fullscreen();
}
- PtyInstruction::ClosePane(id) => {
- pty_bus.close_pane(id);
- command_is_executing.done_closing_pane();
+ ScreenInstruction::NewTab(pane_id) => {
+ screen.new_tab(pane_id);
+ command_is_executing.done_opening_new_pane();
}
- PtyInstruction::CloseTab(ids) => {
- pty_bus.close_tab(ids);
- command_is_executing.done_closing_pane();
+ ScreenInstruction::SwitchTabNext => screen.switch_tab_next(),
+ ScreenInstruction::SwitchTabPrev => screen.switch_tab_prev(),
+ ScreenInstruction::CloseTab => screen.close_tab(),
+ ScreenInstruction::ApplyLayout((layout, new_pane_pids)) => {
+ screen.apply_layout(layout, new_pane_pids);
+ command_is_executing.done_opening_new_pane();
}
- PtyInstruction::Quit => {
+ ScreenInstruction::Quit => {
break;
}
}
}
- })
- .unwrap(),
- );
-
- active_threads.push(
- thread::Builder::new()
- .name("screen".to_string())
- .spawn({
- let mut command_is_executing = command_is_executing.clone();
- let os_input = os_input.clone();
- let send_pty_instructions = send_pty_instructions.clone();
- let send_plugin_instructions = send_plugin_instructions.clone();
- let send_app_instructions = send_app_instructions.clone();
- let max_panes = opts.max_panes;
+ }
+ })
+ .unwrap();
- move || {
- let mut screen = Screen::new(
- receive_screen_instructions,
- send_pty_instructions,
- send_plugin_instructions,
- send_app_instructions,
- &full_screen_ws,
- os_input,
- max_panes,
- );
- loop {
- let (event, mut err_ctx) = screen
- .receiver
- .recv()
- .expect("failed to receive event on channel");
- err_ctx.add_call(ContextType::Screen(ScreenContext::from(&event)));
- screen.send_app_instructions.update(err_ctx);
- screen.send_pty_instructions.update(err_ctx);
- match event {
- ScreenInstruction::Pty(pid, vte_event) => {
- screen
- .get_active_tab_mut()
- .unwrap()
- .handle_pty_event(pid, vte_event);
- }
- ScreenInstruction::Render => {
- screen.render();
- }
- ScreenInstruction::NewPane(pid) => {
- screen.get_active_tab_mut().unwrap().new_pane(pid);
- command_is_executing.done_opening_new_pane();
- }
- ScreenInstruction::HorizontalSplit(pid) => {
- screen.get_active_tab_mut().unwrap().horizontal_split(pid);
- command_is_executing.done_opening_new_pane();
- }
- ScreenInstruction::VerticalSplit(pid) => {
- screen.get_active_tab_mut().unwrap().vertical_split(pid);
- command_is_executing.done_opening_new_pane();
- }
- ScreenInstruction::WriteCharacter(bytes) => {
- screen
- .get_active_tab_mut()
- .unwrap()
- .write_to_active_terminal(bytes);
- }
- ScreenInstruction::ResizeLeft => {
- screen.get_active_tab_mut().unwrap().resize_left();
- }
- ScreenInstruction::ResizeRight => {
- screen.get_active_tab_mut().unwrap().resize_right();
- }
- ScreenInstruction::ResizeDown => {
- screen.get_active_tab_mut().unwrap().resize_down();
- }
- ScreenInstruction::ResizeUp => {
- screen.get_active_tab_mut().unwrap().resize_up();
- }
- ScreenInstruction::MoveFocus => {
- screen.get_active_tab_mut().unwrap().move_focus();
- }
- ScreenInstruction::MoveFocusLeft => {
- screen.get_active_tab_mut().unwrap().move_focus_left();
- }
- ScreenInstruction::MoveFocusDown => {
- screen.get_active_tab_mut().unwrap().move_focus_down();
- }
- ScreenInstruction::MoveFocusRight => {
- screen.get_active_tab_mut().unwrap().move_focus_right();
- }
- ScreenInstruction::MoveFocusUp => {
- screen.get_active_tab_mut().unwrap().move_focus_up();
- }
- ScreenInstruction::ScrollUp => {
- screen
- .get_active_tab_mut()
- .unwrap()
- .scroll_active_terminal_up();
- }
- ScreenInstruction::ScrollDown => {
- screen
- .get_active_tab_mut()
- .unwrap()
- .scroll_active_terminal_down();
- }
- ScreenInstruction::ClearScroll => {
- screen
- .get_active_tab_mut()
- .unwrap()
- .clear_active_terminal_scroll();
- }
- ScreenInstruction::CloseFocusedPane => {
- screen.get_active_tab_mut().unwrap().close_focused_pane();
- screen.render();
- }
- ScreenInstruction::SetSelectable(id, selectable) => {
- screen
- .get_active_tab_mut()
- .unwrap()
- .set_pane_selectable(id, selectable);
- // FIXME: Is this needed?
- screen.render();
- }
- ScreenInstruction::ClosePane(id) => {
- screen.get_active_tab_mut().unwrap().close_pane(id);
- screen.render();
- }
- ScreenInstruction::ToggleActiveTerminalFullscreen => {
- screen
- .get_active_tab_mut()
- .unwrap()
- .toggle_active_pane_fullscreen();
- }
- ScreenInstruction::NewTab(pane_id) => {
- screen.new_tab(pane_id);
- command_is_executing.done_opening_new_pane();
- }
- ScreenInstruction::SwitchTabNext => screen.switch_tab_next(),
- ScreenInstruction::SwitchTabPrev => screen.switch_tab_prev(),
- ScreenInstruction::CloseTab => screen.close_tab(),
- ScreenInstruction::ApplyLayout((layout, new_pane_pids)) => {
- screen.apply_layout(layout, new_pane_pids);
- command_is_executing.done_opening_new_pane();
- }
- ScreenInstruction::Quit => {
- break;
- }
- }
- }
- }
- })
- .unwrap(),
- );
+ let wasm_thread = thread::Builder::new()
+ .name("wasm".to_string())
+ .spawn({
+ let mut send_pty_instructions = send_pty_instructions.clone();
+ let mut send_screen_instructions = send_screen_instructions.clone();
+ let mut send_app_instructions = send_app_instructions.clone();
- active_threads.push(
- thread::Builder::new()
- .name("wasm".to_string())
- .spawn({
- let mut send_pty_instructions = send_pty_instructions.clone();
- let mut send_screen_instructions = send_screen_instructions.clone();
- let mut send_app_instructions = send_app_instructions.clone();
+ let store = Store::default();
+ let mut plugin_id = 0;
+ let mut plugin_map = HashMap::new();
- let store = Store::default();
- let mut plugin_id = 0;
- let mut plugin_map = HashMap::new();
+ move || loop {
+ let (event, mut err_ctx) = receive_plugin_instructions
+ .recv()
+ .expect("failed to receive event on channel");
+ err_ctx.add_call(ContextType::Plugin(PluginContext::from(&event)));
+ send_screen_instructions.update(err_ctx);
+ send_pty_instructions.update(err_ctx);
+ send_app_instructions.update(err_ctx);
+ match event {
+ PluginInstruction::Load(pid_tx, path) => {
+ let project_dirs =
+ ProjectDirs::from("org", "Mosaic Contributors", "Mosaic").unwrap();
+ let plugin_dir = project_dirs.data_dir().join("plugins/");
+ let wasm_bytes = fs::read(&path)
+ .or_else(|_| fs::read(&path.with_extension("wasm")))
+ .or_else(|_| fs::read(&plugin_dir.join(&path).with_extension("wasm")))
+ .unwrap_or_else(|_| panic!("cannot find plugin {}", &path.display()));
- move || loop {
- let (event, mut err_ctx) = receive_plugin_instructions
- .recv()
- .expect("failed to receive event on channel");
- err_ctx.add_call(ContextType::Plugin(PluginContext::from(&event)));
- send_screen_instructions.update(err_ctx);
- send_pty_instructions.update(err_ctx);
- send_app_instructions.update(err_ctx);
- match event {
- PluginInstruction::Load(pid_tx, path) => {
- let project_dirs =
- ProjectDirs::from("org", "Mosaic Contributors", "Mosaic").unwrap();
- let plugin_dir = project_dirs.data_dir().join("plugins/");
- let wasm_bytes = fs::read(&path)
- .or_else(|_| fs::read(&path.with_extension("wasm")))
- .or_else(|_| {
- fs::read(&plugin_dir.join(&path).with_extension("wasm"))
- })
- .unwrap_or_else(|_| {
- panic!("cannot find plugin {}", &path.display())
- });
+ // FIXME: Cache this compiled module on disk. I could use `(de)serialize_to_file()` for that
+ let module = Module::new(&store, &wasm_bytes).unwrap();
- // FIXME: Cache this compiled module on disk. I could use `(de)serialize_to_file()` for that
- let module = Module::new(&store, &wasm_bytes).unwrap();
+ let output = Pipe::new();
+ let input = Pipe::new();
+ let mut wasi_env = WasiState::new("mosaic")
+ .env("CLICOLOR_FORCE", "1")
+ .preopen(|p| {
+ p.directory(".") // FIXME: Change this to a more meaningful dir
+ .alias(".")
+ .read(true)
+ .write(true)
+ .create(true)
+ })
+ .unwrap()
+ .stdin(Box::new(input))
+ .stdout(Box::new(output))
+ .finalize()
+ .unwrap();
- let output = Pipe::new();
- let input = Pipe::new();
- let mut wasi_env = WasiState::new("mosaic")
- .env("CLICOLOR_FORCE", "1")
- .preopen(|p| {
- p.directory(".") // FIXME: Change this to a more meaningful dir
- .alias(".")
- .read(true)
- .write(true)
- .create(true)
- })
- .unwrap()
- .stdin(Box::new(input))
- .stdout(Box::new(output))
- .finalize()
- .unwrap();
+ let wasi = wasi_env.import_object(&module).unwrap();
- let wasi = wasi_env.import_object(&module).unwrap();
+ let plugin_env = PluginEnv {
+ plugin_id,
+ send_pty_instructions: send_pty_instructions.clone(),
+ send_screen_instructions: send_screen_instructions.clone(),
+ send_app_instructions: send_app_instructions.clone(),
+ wasi_env,
+ };
- let plugin_env = PluginEnv {
- plugin_id,
- send_pty_instructions: send_pty_instructions.clone(),
- send_screen_instructions: send_screen_instructions.clone(),
- send_app_instructions: send_app_instructions.clone(),
- wasi_env,
- };
+ let mosaic = mosaic_imports(&store, &plugin_env);
+ let instance = Instance::new(&module, &mosaic.chain_back(wasi)).unwrap();
- let mosaic = mosaic_imports(&store, &plugin_env);
- let instance =
- Instance::new(&module, &mosaic.chain_back(wasi)).unwrap();
+ let start = instance.exports.get_function("_start").unwrap();
- let start = instance.exports.get_function("_start").unwrap();
+ // This eventually calls the `.init()` method
+ start.call(&[]).unwrap();
- // This eventually calls the `.init()` method
- start.call(&[]).unwrap();
+ plugin_map.insert(plugin_id, (instance, plugin_env));
+ pid_tx.send(plugin_id).unwrap();
+ plugin_id += 1;
+ }
+ PluginInstruction::Draw(buf_tx, pid, rows, cols) => {
+ let (instance, plugin_env) = plugin_map.get(&pid).unwrap();
- plugin_map.insert(plugin_id, (instance, plugin_env));
- pid_tx.send(plugin_id).unwrap();
- plugin_id += 1;
- }
- PluginInstruction::Draw(buf_tx, pid, rows, cols) => {
- let (instance, plugin_env) = plugin_map.get(&pid).unwrap();
+ let draw = instance.exports.get_function("draw").unwrap();
- let draw = instance.exports.get_function("draw").unwrap();
+ draw.call(&[Value::I32(rows as i32), Value::I32(cols as i32)])
+ .unwrap();
- draw.call(&[Value::I32(rows as i32), Value::I32(cols as i32)])
- .unwrap();
+ buf_tx.send(wasi_stdout(&plugin_env.wasi_env)).unwrap();
+ }
+ // FIXME: Deduplicate this with the callback below!
+ PluginInstruction::Input(pid, input_bytes) => {
+ let (instance, plugin_env) = plugin_map.get(&pid).unwrap();
- buf_tx.send(wasi_stdout(&plugin_env.wasi_env)).unwrap();
+ let handle_key = instance.exports.get_function("handle_key").unwrap();
+ for key in input_bytes.keys() {
+ if let Ok(key) = key {
+ wasi_write_string(
+ &plugin_env.wasi_env,
+ &serde_json::to_string(&key).unwrap(),
+ );
+ handle_key.call(&[]).unwrap();
+ }
}
- // FIXME: Deduplicate this with the callback below!
- PluginInstruction::Input(pid, input_bytes) => {
- let (instance, plugin_env) = plugin_map.get(&pid).unwrap();
- let handle_key = instance.exports.get_function("handle_key").unwrap();
+ drop(send_screen_instructions.send(ScreenInstruction::Render));
+ }
+ PluginInstruction::GlobalInput(input_bytes) => {
+ // FIXME: Set up an event subscription system, and timed callbacks
+ for (instance, plugin_env) in plugin_map.values() {
+ let handler =
+ instance.exports.get_function("handle_global_key").unwrap();
for key in input_bytes.keys() {
if let Ok(key) = key {
wasi_write_string(
&plugin_env.wasi_env,
&serde_json::to_string(&key).unwrap(),
);
- handle_key.call(&[]).unwrap();
+ handler.call(&[]).unwrap();
}
}
-
- drop(send_screen_instructions.send(ScreenInstruction::Render));
}
- PluginInstruction::GlobalInput(input_bytes) => {
- // FIXME: Set up an event subscription system, and timed callbacks
- for (instance, plugin_env) in plugin_map.values() {
- let handler =
- instance.exports.get_function("handle_global_key").unwrap();
- for key in input_bytes.keys() {
- if let Ok(key) = key {
- wasi_write_string(
- &plugin_env.wasi_env,
- &serde_json::to_string(&key).unwrap(),
- );
- handler.call(&[]).unwrap();
- }
- }
- }
- drop(send_screen_instructions.send(ScreenInstruction::Render));
- }
- PluginInstruction::Unload(pid) => drop(plugin_map.remove(&pid)),
- PluginInstruction::Quit => break,
+ drop(send_screen_instructions.send(ScreenInstruction::Render));
}
+ PluginInstruction::Unload(pid) => drop(plugin_map.remove(&pid)),
+ PluginInstruction::Quit => break,
}
- })
- .unwrap(),
- );
+ }
+ })
+ .unwrap();
- // TODO: currently we don't push this into active_threads
+ // TODO: currently we don't wait for this to quit
// because otherwise the app will hang. Need to fix this so it both
// listens to the ipc-bus and is able to quit cleanly
#[cfg(not(test))]
@@ -663,8 +651,11 @@ pub fn start(mut os_input: Box<dyn OsApi>, opts: CliArgs) {
}
AppInstruction::Error(backtrace) => {
let _ = send_screen_instructions.send(ScreenInstruction::Quit);
+ let _ = screen_thread.join();
let _ = send_pty_instructions.send(PtyInstruction::Quit);
+ let _ = pty_thread.join();
let _ = send_plugin_instructions.send(PluginInstruction::Quit);
+ let _ = wasm_thread.join();
os_input.unset_raw_mode(0);
let goto_start_of_last_line = format!("\u{1b}[{};{}H", full_screen_ws.rows, 1);
let error = format!("{}\n{}", goto_start_of_last_line, backtrace);
@@ -672,17 +663,17 @@ pub fn start(mut os_input: Box<dyn OsApi>, opts: CliArgs) {
.get_stdout_writer()
.write(error.as_bytes())
.unwrap();
- for thread_handler in active_threads {
- let _ = thread_handler.join();
- }
std::process::exit(1);
}
}
}
- for thread_handler in active_threads {
- thread_handler.join().unwrap();
- }
+ let _ = send_screen_instructions.send(ScreenInstruction::Quit);
+ screen_thread.join().unwrap();
+ let _ = send_pty_instructions.send(PtyInstruction::Quit);
+ pty_thread.join().unwrap();
+ let _ = send_plugin_instructions.send(PluginInstruction::Quit);
+ wasm_thread.join().unwrap();
// cleanup();
let reset_style = "\u{1b}[m";
diff --git a/src/screen.rs b/src/screen.rs
index 5e4d1ae9..7fb19b6c 100644
--- a/src/screen.rs
+++ b/src/screen.rs
@@ -146,7 +146,9 @@ impl Screen {
.unwrap();
if self.tabs.is_empty() {
self.active_tab_index = None;
- self.render();
+ self.send_app_instructions
+ .send(AppInstruction::Exit)
+ .unwrap();
}
}
pub fn render(&mut self) {
@@ -156,10 +158,6 @@ impl Screen {
} else {
self.close_tab();
}
- } else {
- self.send_app_instructions
- .send(AppInstruction::Exit)
- .unwrap();
};
}