Skip to content

Commit

Permalink
Trap panics and silence bad pipe errors (#862)
Browse files Browse the repository at this point in the history
  • Loading branch information
mitsuhiko authored Mar 10, 2024
1 parent 3d5cc59 commit e497653
Show file tree
Hide file tree
Showing 4 changed files with 59 additions and 21 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ _Unreleased_

- Updated to `uv` 0.1.6. #850

- Trap panics and silence bad pipe errors. #862

## 0.28.0

Released on 2024-03-07
Expand Down
45 changes: 24 additions & 21 deletions rye/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use std::process;
use std::sync::atomic::{AtomicBool, Ordering};

use crate::utils::panic::trap_bad_pipe;
use crate::utils::QuietExit;

#[macro_use]
Expand Down Expand Up @@ -34,6 +34,8 @@ pub fn disable_ctrlc_handler() {
}

pub fn main() {
crate::utils::panic::set_panic_hook();

ctrlc::set_handler(move || {
if !DISABLE_CTRLC_HANDLER.load(Ordering::Relaxed) {
let term = console::Term::stderr();
Expand All @@ -48,26 +50,27 @@ pub fn main() {
})
.unwrap();

let result = cli::execute();
let status = match result {
Ok(()) => 0,
Err(err) => {
if let Some(err) = err.downcast_ref::<clap::Error>() {
err.print().ok();
err.exit_code()
} else if let Some(QuietExit(code)) = err.downcast_ref() {
*code
} else {
error!("{:?}", err);
1
trap_bad_pipe(|| {
let result = cli::execute();
let status = match result {
Ok(()) => 0,
Err(err) => {
if let Some(err) = err.downcast_ref::<clap::Error>() {
err.print().ok();
err.exit_code()
} else if let Some(QuietExit(code)) = err.downcast_ref() {
*code
} else {
error!("{:?}", err);
1
}
}
}
};
};

if SHOW_CONTINUE_PROMPT.load(Ordering::Relaxed) {
echo!("Press any key to continue");
console::Term::buffered_stderr().read_key().ok();
}

process::exit(status);
if SHOW_CONTINUE_PROMPT.load(Ordering::Relaxed) {
echo!("Press any key to continue");
console::Term::buffered_stderr().read_key().ok();
}
status
});
}
1 change: 1 addition & 0 deletions rye/src/utils/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ pub(crate) mod windows;
#[cfg(unix)]
pub(crate) mod unix;

pub(crate) mod panic;
pub(crate) mod ruff;
pub(crate) mod toml;

Expand Down
32 changes: 32 additions & 0 deletions rye/src/utils/panic.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
use std::any::Any;
use std::{panic, process};

fn is_bad_pipe(payload: &dyn Any) -> bool {
payload
.downcast_ref::<String>()
.map_or(false, |x| x.contains("failed printing to stdout: "))
}

/// Registers a panic hook that hides stdout printing failures.
pub fn set_panic_hook() {
let default_hook = panic::take_hook();
panic::set_hook(Box::new(move |info| {
if !is_bad_pipe(info.payload()) {
default_hook(info)
}
}));
}

/// Catches down panics that are caused by bad pipe errors.
pub fn trap_bad_pipe<F: FnOnce() -> i32 + Send + Sync>(f: F) -> ! {
process::exit(match panic::catch_unwind(panic::AssertUnwindSafe(f)) {
Ok(status) => status,
Err(panic) => {
if is_bad_pipe(&panic) {
1
} else {
panic::resume_unwind(panic);
}
}
});
}

0 comments on commit e497653

Please sign in to comment.