errors: Don't unwrap in server::terminal_bytes (#1876)
* server/terminal_bytes: Don't unwrap and return `Result`s instead, where appropriate. * changelog: Add PR #1876 Don't unwrap in `zellij_server::terminal_bytes`.
This commit is contained in:
parent
086b5d28fb
commit
60322e969f
3 changed files with 40 additions and 18 deletions
|
|
@ -13,6 +13,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
|
||||||
* debugging: Remove calls to unwrap in `zellij_server::ui::*` (https://github.com/zellij-org/zellij/pull/1870)
|
* debugging: Remove calls to unwrap in `zellij_server::ui::*` (https://github.com/zellij-org/zellij/pull/1870)
|
||||||
* debugging: Remove calls to unwrap in `zellij_server::pty_writer` (https://github.com/zellij-org/zellij/pull/1872)
|
* debugging: Remove calls to unwrap in `zellij_server::pty_writer` (https://github.com/zellij-org/zellij/pull/1872)
|
||||||
* docs(example): update the format of the themes for the example directory (https://github.com/zellij-org/zellij/pull/1877)
|
* docs(example): update the format of the themes for the example directory (https://github.com/zellij-org/zellij/pull/1877)
|
||||||
|
* debugging: Remove calls to unwrap in `zellij_server::terminal_bytes` (https://github.com/zellij-org/zellij/pull/1876)
|
||||||
|
|
||||||
## [0.32.0] - 2022-10-25
|
## [0.32.0] - 2022-10-25
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -455,20 +455,23 @@ impl Pty {
|
||||||
.ok_or_else(|| SpawnTerminalError::GenericSpawnError("os input is none"))?
|
.ok_or_else(|| SpawnTerminalError::GenericSpawnError("os input is none"))?
|
||||||
.spawn_terminal(terminal_action, quit_cb, self.default_editor.clone())?;
|
.spawn_terminal(terminal_action, quit_cb, self.default_editor.clone())?;
|
||||||
let terminal_bytes = task::spawn({
|
let terminal_bytes = task::spawn({
|
||||||
let err_context = || format!("failed to run async task for terminal {terminal_id}");
|
let err_context =
|
||||||
|
|terminal_id: u32| format!("failed to run async task for terminal {terminal_id}");
|
||||||
let senders = self.bus.senders.clone();
|
let senders = self.bus.senders.clone();
|
||||||
let os_input = self
|
let os_input = self
|
||||||
.bus
|
.bus
|
||||||
.os_input
|
.os_input
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.with_context(err_context)
|
.with_context(|| err_context(terminal_id))
|
||||||
.fatal()
|
.fatal()
|
||||||
.clone();
|
.clone();
|
||||||
let debug_to_file = self.debug_to_file;
|
let debug_to_file = self.debug_to_file;
|
||||||
async move {
|
async move {
|
||||||
TerminalBytes::new(pid_primary, senders, os_input, debug_to_file, terminal_id)
|
TerminalBytes::new(pid_primary, senders, os_input, debug_to_file, terminal_id)
|
||||||
.listen()
|
.listen()
|
||||||
.await;
|
.await
|
||||||
|
.with_context(|| err_context(terminal_id))
|
||||||
|
.fatal();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -657,7 +660,9 @@ impl Pty {
|
||||||
terminal_id,
|
terminal_id,
|
||||||
)
|
)
|
||||||
.listen()
|
.listen()
|
||||||
.await;
|
.await
|
||||||
|
.context("failed to spawn terminals for layout")
|
||||||
|
.fatal();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
self.task_handles.insert(terminal_id, terminal_bytes);
|
self.task_handles.insert(terminal_id, terminal_bytes);
|
||||||
|
|
@ -758,20 +763,23 @@ impl Pty {
|
||||||
.ok_or_else(|| SpawnTerminalError::GenericSpawnError("os input is none"))?
|
.ok_or_else(|| SpawnTerminalError::GenericSpawnError("os input is none"))?
|
||||||
.re_run_command_in_terminal(id, run_command, quit_cb)?;
|
.re_run_command_in_terminal(id, run_command, quit_cb)?;
|
||||||
let terminal_bytes = task::spawn({
|
let terminal_bytes = task::spawn({
|
||||||
let err_context = || format!("failed to run async task for pane {pane_id:?}");
|
let err_context =
|
||||||
|
|pane_id| format!("failed to run async task for pane {pane_id:?}");
|
||||||
let senders = self.bus.senders.clone();
|
let senders = self.bus.senders.clone();
|
||||||
let os_input = self
|
let os_input = self
|
||||||
.bus
|
.bus
|
||||||
.os_input
|
.os_input
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.with_context(err_context)
|
.with_context(|| err_context(pane_id))
|
||||||
.fatal()
|
.fatal()
|
||||||
.clone();
|
.clone();
|
||||||
let debug_to_file = self.debug_to_file;
|
let debug_to_file = self.debug_to_file;
|
||||||
async move {
|
async move {
|
||||||
TerminalBytes::new(pid_primary, senders, os_input, debug_to_file, id)
|
TerminalBytes::new(pid_primary, senders, os_input, debug_to_file, id)
|
||||||
.listen()
|
.listen()
|
||||||
.await;
|
.await
|
||||||
|
.with_context(|| err_context(pane_id))
|
||||||
|
.fatal();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@ use std::{
|
||||||
};
|
};
|
||||||
use zellij_utils::{
|
use zellij_utils::{
|
||||||
async_std,
|
async_std,
|
||||||
errors::{get_current_ctx, ContextType},
|
errors::{get_current_ctx, prelude::*, ContextType},
|
||||||
logging::debug_to_file,
|
logging::debug_to_file,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -63,7 +63,7 @@ impl TerminalBytes {
|
||||||
last_render: Instant::now(),
|
last_render: Instant::now(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub async fn listen(&mut self) {
|
pub async fn listen(&mut self) -> Result<()> {
|
||||||
// This function reads bytes from the pty and then sends them as
|
// This function reads bytes from the pty and then sends them as
|
||||||
// ScreenInstruction::PtyBytes to screen to be parsed there
|
// ScreenInstruction::PtyBytes to screen to be parsed there
|
||||||
// We also send a separate instruction to Screen to render as ScreenInstruction::Render
|
// We also send a separate instruction to Screen to render as ScreenInstruction::Render
|
||||||
|
|
@ -75,6 +75,8 @@ impl TerminalBytes {
|
||||||
// only send a render instruction sparingly, giving screen time to process bytes and render
|
// only send a render instruction sparingly, giving screen time to process bytes and render
|
||||||
// while still allowing the user to see an indication that things are happening (the
|
// while still allowing the user to see an indication that things are happening (the
|
||||||
// sparing render instructions)
|
// sparing render instructions)
|
||||||
|
let err_context = || "failed to listen for bytes from PTY".to_string();
|
||||||
|
|
||||||
let mut err_ctx = get_current_ctx();
|
let mut err_ctx = get_current_ctx();
|
||||||
err_ctx.add_call(ContextType::AsyncTask);
|
err_ctx.add_call(ContextType::AsyncTask);
|
||||||
let mut buf = [0u8; 65536];
|
let mut buf = [0u8; 65536];
|
||||||
|
|
@ -82,8 +84,10 @@ impl TerminalBytes {
|
||||||
match self.deadline_read(&mut buf).await {
|
match self.deadline_read(&mut buf).await {
|
||||||
ReadResult::Ok(0) | ReadResult::Err(_) => break, // EOF or error
|
ReadResult::Ok(0) | ReadResult::Err(_) => break, // EOF or error
|
||||||
ReadResult::Timeout => {
|
ReadResult::Timeout => {
|
||||||
let time_to_send_render =
|
let time_to_send_render = self
|
||||||
self.async_send_to_screen(ScreenInstruction::Render).await;
|
.async_send_to_screen(ScreenInstruction::Render)
|
||||||
|
.await
|
||||||
|
.with_context(err_context)?;
|
||||||
self.update_render_send_time(time_to_send_render);
|
self.update_render_send_time(time_to_send_render);
|
||||||
// next read does not need a deadline as we just rendered everything
|
// next read does not need a deadline as we just rendered everything
|
||||||
self.render_deadline = None;
|
self.render_deadline = None;
|
||||||
|
|
@ -98,11 +102,14 @@ impl TerminalBytes {
|
||||||
self.terminal_id,
|
self.terminal_id,
|
||||||
bytes.to_vec(),
|
bytes.to_vec(),
|
||||||
))
|
))
|
||||||
.await;
|
.await
|
||||||
|
.with_context(err_context)?;
|
||||||
if !self.backed_up {
|
if !self.backed_up {
|
||||||
// we're not backed up, let's send an immediate render instruction
|
// we're not backed up, let's send an immediate render instruction
|
||||||
let time_to_send_render =
|
let time_to_send_render = self
|
||||||
self.async_send_to_screen(ScreenInstruction::Render).await;
|
.async_send_to_screen(ScreenInstruction::Render)
|
||||||
|
.await
|
||||||
|
.with_context(err_context)?;
|
||||||
self.update_render_send_time(time_to_send_render);
|
self.update_render_send_time(time_to_send_render);
|
||||||
self.last_render = Instant::now();
|
self.last_render = Instant::now();
|
||||||
}
|
}
|
||||||
|
|
@ -113,16 +120,22 @@ impl TerminalBytes {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
self.async_send_to_screen(ScreenInstruction::Render).await;
|
self.async_send_to_screen(ScreenInstruction::Render)
|
||||||
|
.await
|
||||||
|
.with_context(err_context)?;
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
async fn async_send_to_screen(&self, screen_instruction: ScreenInstruction) -> Duration {
|
async fn async_send_to_screen(
|
||||||
|
&self,
|
||||||
|
screen_instruction: ScreenInstruction,
|
||||||
|
) -> Result<Duration> {
|
||||||
// returns the time it blocked the thread for
|
// returns the time it blocked the thread for
|
||||||
let sent_at = Instant::now();
|
let sent_at = Instant::now();
|
||||||
let senders = self.senders.clone();
|
let senders = self.senders.clone();
|
||||||
task::spawn_blocking(move || senders.send_to_screen(screen_instruction))
|
task::spawn_blocking(move || senders.send_to_screen(screen_instruction))
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.context("failed to async-send to screen")?;
|
||||||
sent_at.elapsed()
|
Ok(sent_at.elapsed())
|
||||||
}
|
}
|
||||||
fn update_render_send_time(&mut self, time_to_send_render: Duration) {
|
fn update_render_send_time(&mut self, time_to_send_render: Duration) {
|
||||||
match self.minimum_render_send_time.as_mut() {
|
match self.minimum_render_send_time.as_mut() {
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue