Don't panic if the other end of std{out,err} is closed (#4179)

* fix #4161

println! and friends will panic on BrokenPipe. The solution is to use
writeln! instead, and ignore the error (or do we want to do something else?)

* test that nu doesn't panic in case of BrokenPipe error

* fixup! test that nu doesn't panic in case of BrokenPipe error

* make do_not_panic_if_broken_pipe only run on UNIX systems
This commit is contained in:
Braulio Valdivielso Martínez 2021-12-20 23:08:41 +00:00 committed by GitHub
parent e919f9a73b
commit d32aec5906
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 30 additions and 3 deletions

View file

@ -6,7 +6,7 @@
macro_rules! out { macro_rules! out {
($($tokens:tt)*) => { ($($tokens:tt)*) => {
use std::io::Write; use std::io::Write;
print!($($tokens)*); write!(std::io::stdout(), $($tokens)*).unwrap_or(());
let _ = std::io::stdout().flush(); let _ = std::io::stdout().flush();
} }
} }
@ -17,7 +17,12 @@ macro_rules! out {
/// and stray printlns left by accident /// and stray printlns left by accident
#[macro_export] #[macro_export]
macro_rules! outln { macro_rules! outln {
($($tokens:tt)*) => { println!($($tokens)*) } ($($tokens:tt)*) => {
{
use std::io::Write;
writeln!(std::io::stdout(), $($tokens)*).unwrap_or(())
}
}
} }
/// Outputs to standard error /// Outputs to standard error
@ -26,7 +31,12 @@ macro_rules! outln {
/// and stray printlns left by accident /// and stray printlns left by accident
#[macro_export] #[macro_export]
macro_rules! errln { macro_rules! errln {
($($tokens:tt)*) => { eprintln!($($tokens)*) } ($($tokens:tt)*) => {
{
use std::io::Write;
writeln!(std::io::stderr(), $($tokens)*).unwrap_or(())
}
}
} }
#[macro_export] #[macro_export]

View file

@ -53,3 +53,20 @@ fn plugins_are_declared_with_wix() {
assert_eq!(actual.out, "0"); assert_eq!(actual.out, "0");
} }
#[test]
#[cfg(not(windows))]
fn do_not_panic_if_broken_pipe() {
// `nu -h | false`
// used to panic with a BrokenPipe error
let child_output = std::process::Command::new("sh")
.arg("-c")
.arg(format!(
"{:?} -h | false",
nu_test_support::fs::executable_path()
))
.output()
.expect("failed to execute process");
assert!(child_output.stderr.is_empty());
}