mirror of
https://github.com/RGBCube/uutils-coreutils
synced 2025-07-27 11:07:44 +00:00
tr: restore default action of SIGPIPE
This commit is contained in:
parent
7e5d3657a5
commit
c1eeed61f3
3 changed files with 29 additions and 9 deletions
|
@ -708,12 +708,16 @@ where
|
||||||
let filtered = buf.iter().filter_map(|&c| translator.translate(c));
|
let filtered = buf.iter().filter_map(|&c| translator.translate(c));
|
||||||
output_buf.extend(filtered);
|
output_buf.extend(filtered);
|
||||||
|
|
||||||
|
#[cfg(not(target_os = "windows"))]
|
||||||
|
output
|
||||||
|
.write_all(&output_buf)
|
||||||
|
.map_err_context(|| get_message("tr-error-write-error"))?;
|
||||||
|
|
||||||
|
// SIGPIPE is not available on Windows.
|
||||||
|
#[cfg(target_os = "windows")]
|
||||||
if let Err(err) = output.write_all(&output_buf) {
|
if let Err(err) = output.write_all(&output_buf) {
|
||||||
// Treat broken pipe as a successful termination, which is the
|
|
||||||
// expected behavior when stdout is a pipeline and the downstream
|
|
||||||
// process terminates.
|
|
||||||
if err.kind() == std::io::ErrorKind::BrokenPipe {
|
if err.kind() == std::io::ErrorKind::BrokenPipe {
|
||||||
break;
|
std::process::exit(13);
|
||||||
} else {
|
} else {
|
||||||
return Err(err.map_err_context(|| get_message("tr-error-write-error")));
|
return Err(err.map_err_context(|| get_message("tr-error-write-error")));
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,10 +13,12 @@ use operation::{
|
||||||
};
|
};
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::ffi::OsString;
|
use std::ffi::OsString;
|
||||||
use std::io::{BufWriter, ErrorKind, Write, stdin, stdout};
|
use std::io::{BufWriter, Write, stdin, stdout};
|
||||||
use uucore::display::Quotable;
|
use uucore::display::Quotable;
|
||||||
use uucore::error::{FromIo, UResult, USimpleError, UUsageError};
|
use uucore::error::{FromIo, UResult, USimpleError, UUsageError};
|
||||||
use uucore::fs::is_stdin_directory;
|
use uucore::fs::is_stdin_directory;
|
||||||
|
#[cfg(not(target_os = "windows"))]
|
||||||
|
use uucore::libc;
|
||||||
use uucore::{format_usage, os_str_as_bytes, show};
|
use uucore::{format_usage, os_str_as_bytes, show};
|
||||||
|
|
||||||
use uucore::locale::{get_message, get_message_with_args};
|
use uucore::locale::{get_message, get_message_with_args};
|
||||||
|
@ -31,6 +33,15 @@ mod options {
|
||||||
|
|
||||||
#[uucore::main]
|
#[uucore::main]
|
||||||
pub fn uumain(args: impl uucore::Args) -> UResult<()> {
|
pub fn uumain(args: impl uucore::Args) -> UResult<()> {
|
||||||
|
// When we receive a SIGPIPE signal, we want to terminate the process so
|
||||||
|
// that we don't print any error messages to stderr. Rust ignores SIGPIPE
|
||||||
|
// (see https://github.com/rust-lang/rust/issues/62569), so we restore it's
|
||||||
|
// default action here.
|
||||||
|
#[cfg(not(target_os = "windows"))]
|
||||||
|
unsafe {
|
||||||
|
libc::signal(libc::SIGPIPE, libc::SIG_DFL);
|
||||||
|
}
|
||||||
|
|
||||||
let matches = uu_app().try_get_matches_from(args)?;
|
let matches = uu_app().try_get_matches_from(args)?;
|
||||||
|
|
||||||
let delete_flag = matches.get_flag(options::DELETE);
|
let delete_flag = matches.get_flag(options::DELETE);
|
||||||
|
@ -157,10 +168,16 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
|
||||||
translate_input(&mut locked_stdin, &mut buffered_stdout, op)?;
|
translate_input(&mut locked_stdin, &mut buffered_stdout, op)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle broken pipe errors gracefully during flush.
|
#[cfg(not(target_os = "windows"))]
|
||||||
|
buffered_stdout
|
||||||
|
.flush()
|
||||||
|
.map_err_context(|| get_message("tr-error-write-error"))?;
|
||||||
|
|
||||||
|
// SIGPIPE is not available on Windows.
|
||||||
|
#[cfg(target_os = "windows")]
|
||||||
match buffered_stdout.flush() {
|
match buffered_stdout.flush() {
|
||||||
Ok(()) => {}
|
Ok(()) => {}
|
||||||
Err(err) if err.kind() == ErrorKind::BrokenPipe => {}
|
Err(err) if err.kind() == std::io::ErrorKind::BrokenPipe => std::process::exit(13),
|
||||||
Err(err) => return Err(err.map_err_context(|| get_message("tr-error-write-error"))),
|
Err(err) => return Err(err.map_err_context(|| get_message("tr-error-write-error"))),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1561,6 +1561,5 @@ fn test_broken_pipe_no_error() {
|
||||||
.args(&["e", "a"])
|
.args(&["e", "a"])
|
||||||
.pipe_in("hello".repeat(100))
|
.pipe_in("hello".repeat(100))
|
||||||
.run_stdout_starts_with(b"")
|
.run_stdout_starts_with(b"")
|
||||||
.success()
|
.fails_silently();
|
||||||
.stderr_is("");
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue