summaryrefslogtreecommitdiffstats
path: root/zellij-server/src/panes
diff options
context:
space:
mode:
authorhar7an <99636919+har7an@users.noreply.github.com>2022-10-23 13:14:24 +0000
committerGitHub <noreply@github.com>2022-10-23 13:14:24 +0000
commit75801bdb0e559c73d3f5ea99f1ce1429a425cd1b (patch)
treeabcc1aa1f941f038ef8d328d6ffa79abfc2ff1a9 /zellij-server/src/panes
parent788bcd6151431222325800e0a46c58384fe0bd22 (diff)
plugins: Improve error handling on plugin version mismatch (#1838)
* server/tab: Don't panic in `Pane::render` and do not crash the application on failure to receive a render update from plugins any longer. Instead, will print a simple string with a hint to check the application logs, where a more thorough error indication can be found. * utils/errors: re-export `anyhow::Error` to create ad-hoc errors with custom error types, without having to wrap them into a `context()` before to turn the into anyhow errors. * plugins: Check plugin version on startup and terminate execution with a descriptive error message in case the plugin version is incompatible with the version of zellij being run. * server/wasm_vm: Add plugin path in version error so the user knows which plugin to look at in case they're using custom plugins. * server/wasm_vm: Check plugin version for equality Previously we would accept cases where the plugin version was newer than the zellij version, which doesn't make a lot of sense. * server/wasm_vm: Prettier error handling in call to `wasmer::Function::call` in case a plugin version mismatch can occur. * tile: Install custom panic handler that will print the panic message to a plugins stdout and then call a panic handler on the host that turns it into a real application-level panic. * tile: Catch errors in event deserialization and turn them into proper panics. These errors are symptomatic of an uncaught plugin version mismatch, for example when developing from main and compiling zellij/the plugins from source. Normal users should never get to see this error. * utils/errors: Improve output in `to_stdout` for anyhow errors. The default anyhow error formatting of `{:?}` is already very good, and we just made it worse by trying to invent our own formatting. * tile: Reword plugin mismatch error message * zellij: Apply rustfmt * changelog: Add PR #1838 Improve error handling on plugin version mismatch. * server/wasm_vm: Rephrase error in passive voice
Diffstat (limited to 'zellij-server/src/panes')
-rw-r--r--zellij-server/src/panes/plugin_pane.rs27
-rw-r--r--zellij-server/src/panes/terminal_pane.rs11
2 files changed, 26 insertions, 12 deletions
diff --git a/zellij-server/src/panes/plugin_pane.rs b/zellij-server/src/panes/plugin_pane.rs
index e872d614a..5709d7fee 100644
--- a/zellij-server/src/panes/plugin_pane.rs
+++ b/zellij-server/src/panes/plugin_pane.rs
@@ -15,6 +15,7 @@ use zellij_utils::shared::ansi_len;
use zellij_utils::{
channels::SenderWithContext,
data::{Event, InputMode, Mouse, PaletteColor},
+ errors::prelude::*,
pane_size::{Dimension, PaneGeom},
shared::make_terminal_title,
};
@@ -137,12 +138,16 @@ impl Pane for PluginPane {
fn render(
&mut self,
client_id: Option<ClientId>,
- ) -> Option<(Vec<CharacterChunk>, Option<String>, Vec<SixelImageChunk>)> {
+ ) -> Result<Option<(Vec<CharacterChunk>, Option<String>, Vec<SixelImageChunk>)>> {
// this is a bit of a hack but works in a pinch
- client_id?;
- let client_id = client_id.unwrap();
+ let client_id = match client_id {
+ Some(id) => id,
+ None => return Ok(None),
+ };
// if self.should_render {
if true {
+ let err_context = || format!("failed to render plugin panes for client {client_id}");
+
// while checking should_render rather than rendering each pane every time
// is more performant, it causes some problems when the pane to the left should be
// rendered and has wide characters (eg. Chinese characters or emoji)
@@ -158,12 +163,16 @@ impl Pane for PluginPane {
self.get_content_rows(),
self.get_content_columns(),
))
- .unwrap();
+ .to_anyhow()
+ .with_context(err_context)?;
self.should_render = false;
+ // This is where we receive the text to render from the plugins.
let contents = buf_rx
.recv()
- .expect("Failed to receive reply from plugin. Please check the logs");
+ .with_context(err_context)
+ .to_log()
+ .unwrap_or("No output from plugin received. See logs".to_string());
for (index, line) in contents.lines().enumerate() {
let actual_len = ansi_len(line);
let line_to_print = if actual_len > self.get_content_columns() {
@@ -185,7 +194,7 @@ impl Pane for PluginPane {
self.get_content_x() + 1,
line_to_print,
)
- .unwrap(); // goto row/col and reset styles
+ .with_context(err_context)?; // goto row/col and reset styles
let line_len = line_to_print.len();
if line_len < self.get_content_columns() {
// pad line
@@ -206,15 +215,15 @@ impl Pane for PluginPane {
y + line_index + 1,
x + 1
)
- .unwrap(); // goto row/col and reset styles
+ .with_context(err_context)?; // goto row/col and reset styles
for _col_index in 0..self.get_content_columns() {
vte_output.push(' ');
}
}
}
- Some((vec![], Some(vte_output), vec![])) // TODO: PluginPanes should have their own grid so that we can return the non-serialized TerminalCharacters and have them participate in the render buffer
+ Ok(Some((vec![], Some(vte_output), vec![]))) // TODO: PluginPanes should have their own grid so that we can return the non-serialized TerminalCharacters and have them participate in the render buffer
} else {
- None
+ Ok(None)
}
}
fn render_frame(
diff --git a/zellij-server/src/panes/terminal_pane.rs b/zellij-server/src/panes/terminal_pane.rs
index 766cfaa2b..8d0651ad2 100644
--- a/zellij-server/src/panes/terminal_pane.rs
+++ b/zellij-server/src/panes/terminal_pane.rs
@@ -17,6 +17,7 @@ use zellij_utils::input::command::RunCommand;
use zellij_utils::pane_size::Offset;
use zellij_utils::{
data::{InputMode, Palette, PaletteColor, Style},
+ errors::prelude::*,
pane_size::SizeInPixels,
pane_size::{Dimension, PaneGeom},
position::Position,
@@ -272,7 +273,7 @@ impl Pane for TerminalPane {
fn render(
&mut self,
_client_id: Option<ClientId>,
- ) -> Option<(Vec<CharacterChunk>, Option<String>, Vec<SixelImageChunk>)> {
+ ) -> Result<Option<(Vec<CharacterChunk>, Option<String>, Vec<SixelImageChunk>)>> {
if self.should_render() {
let mut raw_vte_output = String::new();
let content_x = self.get_content_x();
@@ -332,9 +333,13 @@ impl Pane for TerminalPane {
self.grid.ring_bell = false;
}
self.set_should_render(false);
- Some((character_chunks, Some(raw_vte_output), sixel_image_chunks))
+ Ok(Some((
+ character_chunks,
+ Some(raw_vte_output),
+ sixel_image_chunks,
+ )))
} else {
- None
+ Ok(None)
}
}
fn render_frame(