errors: handle missing plugin caches (#2093)
* server/plugins: Always recreate plugin folders in case they aren't existent and don't mark errors to do so as non-fatal. The latter masks the underlying cause when e.g. the `.cache` folder is, for some reason, not writable by zellij (See #2092), whereas the former fixes problems arising from the user having purged their .cache/zellij folder entirely. * utils/errors: Rewrite panic message * changelog: Add PR #2093
This commit is contained in:
parent
670b9c2759
commit
b274fc5ab1
3 changed files with 58 additions and 58 deletions
|
|
@ -16,6 +16,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
|
|||
* fix: disallow path-like names for sessions (https://github.com/zellij-org/zellij/pull/2082)
|
||||
* errors: Remove more `unwrwap`s from server code (https://github.com/zellij-org/zellij/pull/2069)
|
||||
* fix: support UTF-8 character in tab name and pane name (https://github.com/zellij-org/zellij/pull/2102)
|
||||
* fix: handle missing/inaccessible cache directory (https://github.com/zellij-org/zellij/pull/2093)
|
||||
|
||||
## [0.34.4] - 2022-12-13
|
||||
|
||||
|
|
|
|||
|
|
@ -247,6 +247,15 @@ impl WasmBridge {
|
|||
let plugin_own_data_dir = ZELLIJ_CACHE_DIR.join(Url::from(&plugin.location).to_string());
|
||||
let cache_hit = self.plugin_cache.contains_key(&plugin.path);
|
||||
|
||||
// Create filesystem entries mounted into WASM.
|
||||
// We create them here to get expressive error messages in case they fail.
|
||||
fs::create_dir_all(&plugin_own_data_dir)
|
||||
.with_context(|| format!("failed to create datadir in {plugin_own_data_dir:?}"))
|
||||
.with_context(err_context)?;
|
||||
fs::create_dir_all(ZELLIJ_TMP_DIR.as_path())
|
||||
.with_context(|| format!("failed to create tmpdir at {:?}", &ZELLIJ_TMP_DIR.as_path()))
|
||||
.with_context(err_context)?;
|
||||
|
||||
// We remove the entry here and repopulate it at the very bottom, if everything went well.
|
||||
// We must do that because a `get` will only give us a borrow of the Module. This suffices for
|
||||
// the purpose of setting everything up, but we cannot return a &Module from the "None" match
|
||||
|
|
@ -277,19 +286,6 @@ impl WasmBridge {
|
|||
.with_context(err_context)
|
||||
.fatal();
|
||||
|
||||
fs::create_dir_all(&plugin_own_data_dir)
|
||||
.with_context(|| format!("failed to create datadir in {plugin_own_data_dir:?}"))
|
||||
.with_context(err_context)
|
||||
.non_fatal();
|
||||
|
||||
// ensure tmp dir exists, in case it somehow was deleted (e.g systemd-tmpfiles)
|
||||
fs::create_dir_all(ZELLIJ_TMP_DIR.as_path())
|
||||
.with_context(|| {
|
||||
format!("failed to create tmpdir at {:?}", &ZELLIJ_TMP_DIR.as_path())
|
||||
})
|
||||
.with_context(err_context)
|
||||
.non_fatal();
|
||||
|
||||
let hash: String = PortableHash::default()
|
||||
.hash256(&wasm_bytes)
|
||||
.iter()
|
||||
|
|
@ -310,16 +306,17 @@ impl WasmBridge {
|
|||
Err(e) => {
|
||||
let inner_context = || format!("failed to recover from {e:?}");
|
||||
|
||||
let m = Module::new(&self.store, &wasm_bytes)
|
||||
.with_context(inner_context)
|
||||
.with_context(err_context)?;
|
||||
fs::create_dir_all(ZELLIJ_CACHE_DIR.to_owned())
|
||||
.map_err(anyError::new)
|
||||
.and_then(|_| {
|
||||
Module::new(&self.store, &wasm_bytes).map_err(anyError::new)
|
||||
})
|
||||
.and_then(|m| {
|
||||
m.serialize_to_file(&cached_path).map_err(anyError::new)?;
|
||||
Ok(m)
|
||||
})
|
||||
.with_context(inner_context)
|
||||
.with_context(err_context)?;
|
||||
m.serialize_to_file(&cached_path)
|
||||
.with_context(inner_context)
|
||||
.with_context(err_context)?;
|
||||
m
|
||||
.with_context(err_context)?
|
||||
},
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,9 +16,6 @@ use serde::{Deserialize, Serialize};
|
|||
use std::fmt::{Display, Error, Formatter};
|
||||
use std::path::PathBuf;
|
||||
|
||||
use miette::Diagnostic;
|
||||
use thiserror::Error as ThisError;
|
||||
|
||||
/// Re-exports of common error-handling code.
|
||||
pub mod prelude {
|
||||
pub use super::FatalError;
|
||||
|
|
@ -37,39 +34,6 @@ pub trait ErrorInstruction {
|
|||
fn error(err: String) -> Self;
|
||||
}
|
||||
|
||||
#[derive(Debug, ThisError, Diagnostic)]
|
||||
#[error("{0}{}", self.show_backtrace())]
|
||||
#[diagnostic(help("{}", self.show_help()))]
|
||||
struct Panic(String);
|
||||
|
||||
impl Panic {
|
||||
// We already capture a backtrace with `anyhow` using the `backtrace` crate in the background.
|
||||
// The advantage is that this is the backtrace of the real errors source (i.e. where we first
|
||||
// encountered the error and turned it into an `anyhow::Error`), whereas the backtrace recorded
|
||||
// here is the backtrace leading to the call to any `panic`ing function. Since now we propagate
|
||||
// errors up before `unwrap`ing them (e.g. in `zellij_server::screen::screen_thread_main`), the
|
||||
// former is what we really want to diagnose.
|
||||
// We still keep the second one around just in case the first backtrace isn't meaningful or
|
||||
// non-existent in the first place (Which really shouldn't happen, but you never know).
|
||||
fn show_backtrace(&self) -> String {
|
||||
if let Ok(var) = std::env::var("RUST_BACKTRACE") {
|
||||
if !var.is_empty() && var != "0" {
|
||||
return format!("\n\nPanic backtrace:\n{:?}", backtrace::Backtrace::new());
|
||||
}
|
||||
}
|
||||
"".into()
|
||||
}
|
||||
|
||||
fn show_help(&self) -> String {
|
||||
r#"If you are seeing this message, it means that something went wrong.
|
||||
Please report this error to the github issue.
|
||||
(https://github.com/zellij-org/zellij/issues)
|
||||
|
||||
Also, if you want to see the backtrace, you can set the `RUST_BACKTRACE` environment variable to `1`.
|
||||
"#.into()
|
||||
}
|
||||
}
|
||||
|
||||
/// Helper trait to easily log error types.
|
||||
///
|
||||
/// The `print_error` function takes a closure which takes a `&str` and fares with it as necessary
|
||||
|
|
@ -514,13 +478,51 @@ pub use not_wasm::*;
|
|||
mod not_wasm {
|
||||
use super::*;
|
||||
use crate::channels::{SenderWithContext, ASYNCOPENCALLS, OPENCALLS};
|
||||
use miette::{GraphicalReportHandler, GraphicalTheme, Report};
|
||||
use miette::{Diagnostic, GraphicalReportHandler, GraphicalTheme, Report};
|
||||
use std::panic::PanicInfo;
|
||||
use thiserror::Error as ThisError;
|
||||
|
||||
/// The maximum amount of calls an [`ErrorContext`] will keep track
|
||||
/// of in its stack representation. This is a per-thread maximum.
|
||||
const MAX_THREAD_CALL_STACK: usize = 6;
|
||||
|
||||
#[derive(Debug, ThisError, Diagnostic)]
|
||||
#[error("{0}{}", self.show_backtrace())]
|
||||
#[diagnostic(help("{}", self.show_help()))]
|
||||
struct Panic(String);
|
||||
|
||||
impl Panic {
|
||||
// We already capture a backtrace with `anyhow` using the `backtrace` crate in the background.
|
||||
// The advantage is that this is the backtrace of the real errors source (i.e. where we first
|
||||
// encountered the error and turned it into an `anyhow::Error`), whereas the backtrace recorded
|
||||
// here is the backtrace leading to the call to any `panic`ing function. Since now we propagate
|
||||
// errors up before `unwrap`ing them (e.g. in `zellij_server::screen::screen_thread_main`), the
|
||||
// former is what we really want to diagnose.
|
||||
// We still keep the second one around just in case the first backtrace isn't meaningful or
|
||||
// non-existent in the first place (Which really shouldn't happen, but you never know).
|
||||
fn show_backtrace(&self) -> String {
|
||||
if let Ok(var) = std::env::var("RUST_BACKTRACE") {
|
||||
if !var.is_empty() && var != "0" {
|
||||
return format!("\n\nPanic backtrace:\n{:?}", backtrace::Backtrace::new());
|
||||
}
|
||||
}
|
||||
"".into()
|
||||
}
|
||||
|
||||
fn show_help(&self) -> String {
|
||||
format!(
|
||||
"If you are seeing this message, it means that something went wrong.
|
||||
|
||||
-> To get additional information, check the log at: {}
|
||||
-> To see a backtrace next time, reproduce the error with: RUST_BACKTRACE=1 zellij [...]
|
||||
-> To help us fix this, please open an issue: https://github.com/zellij-org/zellij/issues
|
||||
|
||||
",
|
||||
crate::consts::ZELLIJ_TMP_LOG_FILE.display().to_string()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/// Custom panic handler/hook. Prints the [`ErrorContext`].
|
||||
pub fn handle_panic<T>(info: &PanicInfo<'_>, sender: &SenderWithContext<T>)
|
||||
where
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue