-
Notifications
You must be signed in to change notification settings - Fork 40
diff: exit 141 on a closed output pipe instead of panicking #282
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -4,7 +4,7 @@ | |
| // files that was distributed with this source code. | ||
|
|
||
| use crate::params::{parse_params, Format}; | ||
| use crate::utils::report_failure_to_read_input_file; | ||
| use crate::utils::{exit_on_broken_pipe_or_panic, report_failure_to_read_input_file}; | ||
| use crate::{context_diff, ed_diff, normal_diff, side_diff, unified_diff}; | ||
| use std::env::ArgsOs; | ||
| use std::ffi::OsString; | ||
|
|
@@ -90,8 +90,8 @@ pub fn main(opts: Peekable<ArgsOs>) -> ExitCode { | |
| params.from.to_string_lossy(), | ||
| params.to.to_string_lossy() | ||
| ); | ||
| } else { | ||
| io::stdout().write_all(&result).unwrap(); | ||
| } else if let Err(e) = io::stdout().write_all(&result) { | ||
| exit_on_broken_pipe_or_panic(e); | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. please add a test in tests/integration.rs (closed stdout pipe, and /dev/full) |
||
| } | ||
| if result.is_empty() { | ||
| maybe_report_identical_files(); | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -9,6 +9,7 @@ use std::{io::Write, vec}; | |
| use unicode_width::UnicodeWidthStr; | ||
|
|
||
| use crate::params::Params; | ||
| use crate::utils::exit_on_broken_pipe_or_panic; | ||
|
|
||
| const GUTTER_WIDTH_MIN: usize = 3; | ||
|
|
||
|
|
@@ -350,10 +351,20 @@ pub fn diff<T: Write>( | |
| */ | ||
| for result in diff::slice(&left_lines, &right_lines) { | ||
| match result { | ||
| Result::Left(left_ln) => push_output(left_ln, b"", b'<', output, &config).unwrap(), | ||
| Result::Right(right_ln) => push_output(b"", right_ln, b'>', output, &config).unwrap(), | ||
| Result::Left(left_ln) => { | ||
| if let Err(e) = push_output(left_ln, b"", b'<', output, &config) { | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. almost the same code 3 times. |
||
| exit_on_broken_pipe_or_panic(e); | ||
| } | ||
| } | ||
| Result::Right(right_ln) => { | ||
| if let Err(e) = push_output(b"", right_ln, b'>', output, &config) { | ||
| exit_on_broken_pipe_or_panic(e); | ||
| } | ||
| } | ||
| Result::Both(left_ln, right_ln) => { | ||
| push_output(left_ln, right_ln, b' ', output, &config).unwrap() | ||
| if let Err(e) = push_output(left_ln, right_ln, b' ', output, &config) { | ||
| exit_on_broken_pipe_or_panic(e); | ||
| } | ||
| } | ||
| } | ||
| } | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -7,6 +7,17 @@ use regex::Regex; | |
| use std::{ffi::OsString, io::Write}; | ||
| use unicode_width::UnicodeWidthStr; | ||
|
|
||
| /// Handle a write error to stdout: if the pipe was closed by the reader | ||
| /// (e.g. `diff big1 big2 | head`), exit quietly like GNU does under | ||
| /// `SIGPIPE` (128 + 13 = 141) instead of panicking with a core dump. | ||
| /// Any other write error is a genuine bug, so it still panics. | ||
| pub fn exit_on_broken_pipe_or_panic(e: std::io::Error) -> ! { | ||
| if e.kind() == std::io::ErrorKind::BrokenPipe { | ||
| std::process::exit(141); | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. we don't want |
||
| } | ||
| panic!("{e}"); | ||
| } | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. same for panic other write errors aren't bugs, e.g. |
||
|
|
||
| /// Replace tabs by spaces in the input line. | ||
| /// Correctly handle multi-bytes characters. | ||
| /// This assumes that line does not contain any line breaks (if it does, the result is undefined). | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the
println!for--briefjust above will still panic on a closed pipe, no?