diff options
| author | Kunal Mohan <44079328+kunalmohan@users.noreply.github.com> | 2020-12-09 22:31:26 +0530 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2020-12-09 18:01:26 +0100 |
| commit | 92d1bcff4c0d1d886cefee6984d5533c5ea8dd6f (patch) | |
| tree | 2ef85153a55e61f1d97e03dfa608ac853fe22887 /src/errors.rs | |
| parent | fix(style): else-if ladder -> match (#86) (diff) | |
| download | sl0ppij-92d1bcff4c0d1d886cefee6984d5533c5ea8dd6f.tar.gz sl0ppij-92d1bcff4c0d1d886cefee6984d5533c5ea8dd6f.tar.xz sl0ppij-92d1bcff4c0d1d886cefee6984d5533c5ea8dd6f.zip | |
feat(infrastructure): introduce ErrorContext for tracking errors across threads (#83)
* Implement ErrorContext for tracking errors across threads
* reorder Instruction and ErrorContext
* Add ContextType, AppContext, ScreenContext, PtyContext
* Use ArrayVec in ErrorContext
* increase MAX_THREAD_CALL_STACK to 6
* Custom implement Debug for ErrorContext ad ContextType and color output
* Use os_input instead of println!()
* Use array instead of ArrayVec and some cleanup
* Introduce SenderWithContext
* Keep arrayvec at v0.5.1
Diffstat (limited to 'src/errors.rs')
| -rw-r--r-- | src/errors.rs | 192 |
1 files changed, 184 insertions, 8 deletions
diff --git a/src/errors.rs b/src/errors.rs index 437db0dd..8478969d 100644 --- a/src/errors.rs +++ b/src/errors.rs @@ -1,10 +1,17 @@ -use crate::AppInstruction; +use crate::pty_bus::PtyInstruction; +use crate::screen::ScreenInstruction; +use crate::{AppInstruction, SenderWithContext, OPENCALLS}; use backtrace::Backtrace; +use std::fmt::{Display, Error, Formatter}; use std::panic::PanicInfo; -use std::sync::mpsc::SyncSender; use std::{process, thread}; -pub fn handle_panic(info: &PanicInfo<'_>, send_app_instructions: &SyncSender<AppInstruction>) { +const MAX_THREAD_CALL_STACK: usize = 6; + +pub fn handle_panic( + info: &PanicInfo<'_>, + send_app_instructions: &SenderWithContext<AppInstruction>, +) { let backtrace = Backtrace::new(); let thread = thread::current(); let thread = thread.name().unwrap_or("unnamed"); @@ -14,9 +21,12 @@ pub fn handle_panic(info: &PanicInfo<'_>, send_app_instructions: &SyncSender<App None => info.payload().downcast_ref::<String>().map(|s| &**s), }; + let err_ctx = OPENCALLS.with(|ctx| *ctx.borrow()); + let backtrace = match (info.location(), msg) { (Some(location), Some(msg)) => format!( - "\nthread '{}' panicked at '{}': {}:{}\n{:?}", + "{}\n\u{1b}[0;0mError: \u{1b}[0;31mthread '{}' panicked at '{}': {}:{}\n\u{1b}[0;0m{:?}", + err_ctx, thread, msg, location.file(), @@ -24,17 +34,21 @@ pub fn handle_panic(info: &PanicInfo<'_>, send_app_instructions: &SyncSender<App backtrace ), (Some(location), None) => format!( - "\nthread '{}' panicked: {}:{}\n{:?}", + "{}\n\u{1b}[0;0mError: \u{1b}[0;31mthread '{}' panicked: {}:{}\n\u{1b}[0;0m{:?}", + err_ctx, thread, location.file(), location.line(), backtrace ), (None, Some(msg)) => format!( - "\nthread '{}' panicked at '{}'\n{:?}", - thread, msg, backtrace + "{}\n\u{1b}[0;0mError: \u{1b}[0;31mthread '{}' panicked at '{}'\n\u{1b}[0;0m{:?}", + err_ctx, thread, msg, backtrace + ), + (None, None) => format!( + "{}\n\u{1b}[0;0mError: \u{1b}[0;31mthread '{}' panicked\n\u{1b}[0;0m{:?}", + err_ctx, thread, backtrace ), - (None, None) => format!("\nthread '{}' panicked\n{:?}", thread, backtrace), }; if thread == "main" { @@ -46,3 +60,165 @@ pub fn handle_panic(info: &PanicInfo<'_>, send_app_instructions: &SyncSender<App .unwrap(); } } + +#[derive(Clone, Copy)] +pub struct ErrorContext { + calls: [ContextType; MAX_THREAD_CALL_STACK], +} + +impl ErrorContext { + pub fn new() -> Self { + Self { + calls: [ContextType::Empty; MAX_THREAD_CALL_STACK], + } + } + + pub fn add_call(&mut self, call: ContextType) { + for ctx in self.calls.iter_mut() { + if *ctx == ContextType::Empty { + *ctx = call; + break; + } + } + OPENCALLS.with(|ctx| *ctx.borrow_mut() = *self); + } +} + +impl Display for ErrorContext { + fn fmt(&self, f: &mut Formatter) -> Result<(), Error> { + writeln!(f, "Originating Thread(s):")?; + for (index, ctx) in self.calls.iter().enumerate() { + if *ctx == ContextType::Empty { + break; + } + writeln!(f, "\u{1b}[0;0m{}. {}", index + 1, ctx)?; + } + Ok(()) + } +} + +#[derive(Copy, Clone, PartialEq)] +pub enum ContextType { + Screen(ScreenContext), + Pty(PtyContext), + App(AppContext), + IPCServer, + StdinHandler, + AsyncTask, + Empty, +} + +impl Display for ContextType { + fn fmt(&self, f: &mut Formatter) -> Result<(), Error> { + let purple = "\u{1b}[1;35m"; + let green = "\u{1b}[0;32m"; + match *self { + ContextType::Screen(c) => write!(f, "{}screen_thread: {}{:?}", purple, green, c), + ContextType::Pty(c) => write!(f, "{}pty_thread: {}{:?}", purple, green, c), + ContextType::App(c) => write!(f, "{}main_thread: {}{:?}", purple, green, c), + ContextType::IPCServer => write!(f, "{}ipc_server: {}AcceptInput", purple, green), + ContextType::StdinHandler => { + write!(f, "{}stdin_handler_thread: {}AcceptInput", purple, green) + } + ContextType::AsyncTask => { + write!(f, "{}stream_terminal_bytes: {}AsyncTask", purple, green) + } + ContextType::Empty => write!(f, ""), + } + } +} + +#[derive(Debug, Clone, Copy, PartialEq)] +pub enum ScreenContext { + HandlePtyEvent, + Render, + NewPane, + HorizontalSplit, + VerticalSplit, + WriteCharacter, + ResizeLeft, + ResizeRight, + ResizeDown, + ResizeUp, + MoveFocus, + MoveFocusLeft, + MoveFocusDown, + MoveFocusUp, + MoveFocusRight, + Quit, + ScrollUp, + ScrollDown, + ClearScroll, + CloseFocusedPane, + ToggleActiveTerminalFullscreen, + ClosePane, + ApplyLayout, +} + +impl From<&ScreenInstruction> for ScreenContext { + fn from(screen_instruction: &ScreenInstruction) -> Self { + match *screen_instruction { + ScreenInstruction::Pty(..) => ScreenContext::HandlePtyEvent, + ScreenInstruction::Render => ScreenContext::Render, + ScreenInstruction::NewPane(_) => ScreenContext::NewPane, + ScreenInstruction::HorizontalSplit(_) => ScreenContext::HorizontalSplit, + ScreenInstruction::VerticalSplit(_) => ScreenContext::VerticalSplit, + ScreenInstruction::WriteCharacter(_) => ScreenContext::WriteCharacter, + ScreenInstruction::ResizeLeft => ScreenContext::ResizeLeft, + ScreenInstruction::ResizeRight => ScreenContext::ResizeRight, + ScreenInstruction::ResizeDown => ScreenContext::ResizeDown, + ScreenInstruction::ResizeUp => ScreenContext::ResizeUp, + ScreenInstruction::MoveFocus => ScreenContext::MoveFocus, + ScreenInstruction::MoveFocusLeft => ScreenContext::MoveFocusLeft, + ScreenInstruction::MoveFocusDown => ScreenContext::MoveFocusDown, + ScreenInstruction::MoveFocusUp => ScreenContext::MoveFocusUp, + ScreenInstruction::MoveFocusRight => ScreenContext::MoveFocusRight, + ScreenInstruction::Quit => ScreenContext::Quit, + ScreenInstruction::ScrollUp => ScreenContext::ScrollUp, + ScreenInstruction::ScrollDown => ScreenContext::ScrollDown, + ScreenInstruction::ClearScroll => ScreenContext::ClearScroll, + ScreenInstruction::CloseFocusedPane => ScreenContext::CloseFocusedPane, + ScreenInstruction::ToggleActiveTerminalFullscreen => { + ScreenContext::ToggleActiveTerminalFullscreen + } + ScreenInstruction::ClosePane(_) => ScreenContext::ClosePane, + ScreenInstruction::ApplyLayout(_) => ScreenContext::ApplyLayout, + } + } +} + +#[derive(Debug, Clone, Copy, PartialEq)] +pub enum PtyContext { + SpawnTerminal, + SpawnTerminalVertically, + SpawnTerminalHorizontally, + ClosePane, + Quit, +} + +impl From<&PtyInstruction> for PtyContext { + fn from(pty_instruction: &PtyInstruction) -> Self { + match *pty_instruction { + PtyInstruction::SpawnTerminal(_) => PtyContext::SpawnTerminal, + PtyInstruction::SpawnTerminalVertically(_) => PtyContext::SpawnTerminalVertically, + PtyInstruction::SpawnTerminalHorizontally(_) => PtyContext::SpawnTerminalHorizontally, + PtyInstruction::ClosePane(_) => PtyContext::ClosePane, + PtyInstruction::Quit => PtyContext::Quit, + } + } +} + +#[derive(Debug, Clone, Copy, PartialEq)] +pub enum AppContext { + Exit, + Error, +} + +impl From<&AppInstruction> for AppContext { + fn from(app_instruction: &AppInstruction) -> Self { + match *app_instruction { + AppInstruction::Exit => AppContext::Exit, + AppInstruction::Error(_) => AppContext::Error, + } + } +} |
