mirror of
https://github.com/fish-shell/fish-shell.git
synced 2024-11-25 09:39:52 +08:00
Install a panic handler to avoid dropping crash stacktraces
When fish crashes due to a panic, the terminal window is closed. Some terminals keep the window around when the crash is due to a fatal signal, but today we don't exit via fatal signal on panic. There is the option to set «panic = "abort"» in Cargo.toml, which would give us coredumps but also worse stacktraces on stderr. More importantly it means that we don't unwind, so destructors are skipped I don't think we want that because we should use destructors to restore the terminal state. On crash in interactive fish, read one more line before exiting, so the stack trace is always visible. In future, we should move this "read one line before exiting" logic to where we call "panic!", so I can attach a debugger and see the stacktrace.
This commit is contained in:
parent
ccaf06e9d6
commit
ecdc9ce1dd
|
@ -32,18 +32,18 @@ use fish::{
|
||||||
scoped_push_replacer, str2wcstring, wcs2string, PACKAGE_NAME, PROFILING_ACTIVE,
|
scoped_push_replacer, str2wcstring, wcs2string, PACKAGE_NAME, PROFILING_ACTIVE,
|
||||||
PROGRAM_NAME,
|
PROGRAM_NAME,
|
||||||
},
|
},
|
||||||
env::Statuses,
|
|
||||||
env::{
|
env::{
|
||||||
environment::{env_init, EnvStack, Environment},
|
environment::{env_init, EnvStack, Environment},
|
||||||
ConfigPaths, EnvMode,
|
ConfigPaths, EnvMode, Statuses,
|
||||||
},
|
},
|
||||||
eprintf,
|
eprintf,
|
||||||
event::{self, Event},
|
event::{self, Event},
|
||||||
flog::{self, activate_flog_categories_by_pattern, set_flog_file_fd, FLOG, FLOGF},
|
flog::{self, activate_flog_categories_by_pattern, set_flog_file_fd, FLOG, FLOGF},
|
||||||
fprintf, function, future_feature_flags as features, history,
|
fprintf, function, future_feature_flags as features,
|
||||||
history::start_private_mode,
|
history::{self, start_private_mode},
|
||||||
io::IoChain,
|
io::IoChain,
|
||||||
nix::{getpid, isatty},
|
nix::{getpid, isatty},
|
||||||
|
panic::panic_handler,
|
||||||
parse_constants::{ParseErrorList, ParseTreeFlags},
|
parse_constants::{ParseErrorList, ParseTreeFlags},
|
||||||
parse_tree::ParsedSource,
|
parse_tree::ParsedSource,
|
||||||
parse_util::parse_util_detect_errors_in_ast,
|
parse_util::parse_util_detect_errors_in_ast,
|
||||||
|
@ -465,6 +465,10 @@ fn cstr_from_osstr(s: &OsStr) -> CString {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
|
panic_handler(throwing_main)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn throwing_main() {
|
||||||
let mut args: Vec<WString> = env::args_os()
|
let mut args: Vec<WString> = env::args_os()
|
||||||
.map(|osstr| str2wcstring(osstr.as_bytes()))
|
.map(|osstr| str2wcstring(osstr.as_bytes()))
|
||||||
.collect();
|
.collect();
|
||||||
|
|
|
@ -11,6 +11,7 @@ use std::io::{stdin, Read, Write};
|
||||||
use std::os::unix::ffi::OsStrExt;
|
use std::os::unix::ffi::OsStrExt;
|
||||||
use std::sync::atomic::Ordering;
|
use std::sync::atomic::Ordering;
|
||||||
|
|
||||||
|
use fish::panic::panic_handler;
|
||||||
use libc::{LC_ALL, STDOUT_FILENO};
|
use libc::{LC_ALL, STDOUT_FILENO};
|
||||||
|
|
||||||
use fish::ast::{
|
use fish::ast::{
|
||||||
|
@ -737,8 +738,11 @@ fn char_is_escaped(text: &wstr, idx: usize) -> bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
PROGRAM_NAME.set(L!("fish_indent")).unwrap();
|
panic_handler(throwing_main)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn throwing_main() {
|
||||||
|
PROGRAM_NAME.set(L!("fish_indent")).unwrap();
|
||||||
topic_monitor_init();
|
topic_monitor_init();
|
||||||
threads::init();
|
threads::init();
|
||||||
// Using the user's default locale could be a problem if it doesn't use UTF-8 encoding. That's
|
// Using the user's default locale could be a problem if it doesn't use UTF-8 encoding. That's
|
||||||
|
|
|
@ -25,6 +25,7 @@ use fish::{
|
||||||
fprintf,
|
fprintf,
|
||||||
input::input_terminfo_get_name,
|
input::input_terminfo_get_name,
|
||||||
input_common::{CharEvent, InputEventQueue, InputEventQueuer},
|
input_common::{CharEvent, InputEventQueue, InputEventQueuer},
|
||||||
|
panic::panic_handler,
|
||||||
print_help::print_help,
|
print_help::print_help,
|
||||||
printf,
|
printf,
|
||||||
proc::set_interactive_session,
|
proc::set_interactive_session,
|
||||||
|
@ -364,6 +365,10 @@ fn parse_flags(continuous_mode: &mut bool, verbose: &mut bool) -> bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
|
panic_handler(throwing_main)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn throwing_main() {
|
||||||
PROGRAM_NAME.set(L!("fish_key_reader")).unwrap();
|
PROGRAM_NAME.set(L!("fish_key_reader")).unwrap();
|
||||||
let mut continuous_mode = false;
|
let mut continuous_mode = false;
|
||||||
let mut verbose = false;
|
let mut verbose = false;
|
||||||
|
|
|
@ -68,6 +68,7 @@ pub mod null_terminated_array;
|
||||||
pub mod operation_context;
|
pub mod operation_context;
|
||||||
pub mod output;
|
pub mod output;
|
||||||
pub mod pager;
|
pub mod pager;
|
||||||
|
pub mod panic;
|
||||||
pub mod parse_constants;
|
pub mod parse_constants;
|
||||||
pub mod parse_execution;
|
pub mod parse_execution;
|
||||||
pub mod parse_tree;
|
pub mod parse_tree;
|
||||||
|
|
33
src/panic.rs
Normal file
33
src/panic.rs
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
use std::panic::{catch_unwind, UnwindSafe};
|
||||||
|
|
||||||
|
use libc::STDIN_FILENO;
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
common::{read_blocked, PROGRAM_NAME},
|
||||||
|
nix::isatty,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub fn panic_handler(main: impl FnOnce() + UnwindSafe) -> ! {
|
||||||
|
if !isatty(STDIN_FILENO) {
|
||||||
|
main();
|
||||||
|
unreachable!();
|
||||||
|
}
|
||||||
|
if catch_unwind(main).is_ok() {
|
||||||
|
unreachable!();
|
||||||
|
}
|
||||||
|
printf!(
|
||||||
|
"%s with PID %d crashed, please report a bug. Press Enter to exit",
|
||||||
|
PROGRAM_NAME.get().unwrap(),
|
||||||
|
unsafe { libc::getpid() }
|
||||||
|
);
|
||||||
|
let mut buf = [0_u8; 1];
|
||||||
|
loop {
|
||||||
|
let Ok(n) = read_blocked(STDIN_FILENO, &mut buf) else {
|
||||||
|
std::process::exit(110);
|
||||||
|
};
|
||||||
|
if n == 0 || matches!(buf[0], b'q' | b'\n' | b'\r') {
|
||||||
|
printf!("\n");
|
||||||
|
std::process::exit(110);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user