diff --git a/Cargo.lock b/Cargo.lock index 12c33416..58962bf1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -36,6 +36,28 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f8aac770f1885fd7e387acedd76065302551364496e46b3dd00860b2f8359b9d" +[[package]] +name = "backtrace" +version = "0.3.46" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1e692897359247cc6bb902933361652380af0f1b7651ae5c5013407f30e109e" +dependencies = [ + "backtrace-sys", + "cfg-if", + "libc", + "rustc-demangle", +] + +[[package]] +name = "backtrace-sys" +version = "0.1.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7de8aba10a69c8e8d7622c5710229485ec32e9d55fdad160ea559c086fdcd118" +dependencies = [ + "cc", + "libc", +] + [[package]] name = "base64" version = "0.11.0" @@ -288,12 +310,14 @@ name = "gitui" version = "0.1.2" dependencies = [ "asyncgit", + "backtrace", "crossbeam-channel", "crossterm 0.16.0", "dirs", "itertools 0.9.0", "log", "rayon-core", + "scopeguard", "scopetime", "simplelog", "tui", @@ -680,6 +704,12 @@ dependencies = [ "crossbeam-utils", ] +[[package]] +name = "rustc-demangle" +version = "0.1.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c691c0e608126e00913e33f0ccf3727d5fc84573623b8d65b2df340b5201783" + [[package]] name = "scopeguard" version = "1.1.0" diff --git a/Cargo.toml b/Cargo.toml index 1a24ba6f..3c6d4c84 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -26,6 +26,8 @@ log = "0.4" simplelog = "0.7" dirs = "2.0" crossbeam-channel = "0.4" +scopeguard = "1.1" +backtrace = { version = "0.3" } scopetime = { path = "./scopetime", version = "0.1" } asyncgit = { path = "./asyncgit", version = "0.1" } diff --git a/README.md b/README.md index 0685fd2b..06289f90 100644 --- a/README.md +++ b/README.md @@ -56,7 +56,6 @@ GITUI_LOGGING=true gitui # todo for 0.1 (first release) * [ ] fix audit warnings: https://github.com/Drakulix/simplelog.rs/issues/54 -* [ ] prevent panicking from messing terminal up * [ ] panic on exit (thread sending error) * [ ] better help command * [ ] -> fix: dont show scroll option when any popup open diff --git a/src/main.rs b/src/main.rs index 2f317660..922ed30b 100644 --- a/src/main.rs +++ b/src/main.rs @@ -10,6 +10,7 @@ mod strings; mod ui; use crate::{app::App, poll::QueueEvent}; +use backtrace::Backtrace; use crossbeam_channel::{select, unbounded}; use crossterm::{ terminal::{ @@ -19,15 +20,20 @@ use crossterm::{ ExecutableCommand, Result, }; use log::error; +use scopeguard::defer; use scopetime::scope_time; use simplelog::*; -use std::{env, fs, fs::File, io}; +use std::{env, fs, fs::File, io, panic}; use tui::{backend::CrosstermBackend, Terminal}; fn main() -> Result<()> { setup_logging(); enable_raw_mode()?; io::stdout().execute(EnterAlternateScreen)?; + defer! { + io::stdout().execute(LeaveAlternateScreen).unwrap(); + disable_raw_mode().unwrap(); + } let backend = CrosstermBackend::new(io::stdout()); let mut terminal = Terminal::new(backend)?; @@ -39,13 +45,7 @@ fn main() -> Result<()> { let mut app = App::new(tx_git); - rayon_core::ThreadPoolBuilder::new() - .panic_handler(|e| { - error!("thread panic: {:?}", e); - panic!(e) - }) - .build_global() - .unwrap(); + set_panic_handlers(); let rx_input = poll::start_polling_thread(); @@ -77,8 +77,6 @@ fn main() -> Result<()> { } } - io::stdout().execute(LeaveAlternateScreen)?; - disable_raw_mode()?; Ok(()) } @@ -96,3 +94,20 @@ fn setup_logging() { ); } } + +fn set_panic_handlers() { + // regular panic handler + panic::set_hook(Box::new(|e| { + let backtrace = Backtrace::new(); + error!("panic: {:?}\ntrace:\n{:?}", e, backtrace); + })); + + // threadpool panic handler + rayon_core::ThreadPoolBuilder::new() + .panic_handler(|e| { + error!("thread panic: {:?}", e); + panic!(e) + }) + .build_global() + .unwrap(); +}