Merge pull request #8312 from yuankunzhang/tr-broken-pipe
Some checks are pending
CICD / Style/cargo-deny (push) Waiting to run
CICD / Build (push) Blocked by required conditions
CICD / Style/deps (push) Waiting to run
CICD / Documentation/warnings (push) Waiting to run
CICD / MinRustV (push) Waiting to run
CICD / Test all features separately (push) Blocked by required conditions
CICD / Dependencies (push) Waiting to run
CICD / Build/Makefile (push) Blocked by required conditions
CICD / Build/stable (push) Blocked by required conditions
CICD / Build/nightly (push) Blocked by required conditions
CICD / Binary sizes (push) Blocked by required conditions
CICD / Tests/BusyBox test suite (push) Blocked by required conditions
CICD / Tests/Toybox test suite (push) Blocked by required conditions
CICD / Code Coverage (push) Waiting to run
CICD / Separate Builds (push) Waiting to run
CICD / Build/SELinux (push) Blocked by required conditions
GnuTests / Run GNU tests (push) Waiting to run
Android / Test builds (push) Waiting to run
Code Quality / Style/format (push) Waiting to run
Code Quality / Style/lint (push) Waiting to run
Code Quality / Style/spelling (push) Waiting to run
Code Quality / Style/toml (push) Waiting to run
Code Quality / Style/Python (push) Waiting to run
Code Quality / Pre-commit hooks (push) Waiting to run
FreeBSD / Style and Lint (push) Waiting to run
FreeBSD / Tests (push) Waiting to run

tr: restore default action of sigpipe
This commit is contained in:
Daniel Hofstetter 2025-07-05 14:34:01 +02:00 committed by GitHub
commit a687fbf2b4
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 29 additions and 9 deletions

View file

@ -708,12 +708,16 @@ where
let filtered = buf.iter().filter_map(|&c| translator.translate(c));
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) {
// 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 {
break;
std::process::exit(13);
} else {
return Err(err.map_err_context(|| get_message("tr-error-write-error")));
}

View file

@ -13,10 +13,12 @@ use operation::{
};
use std::collections::HashMap;
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::error::{FromIo, UResult, USimpleError, UUsageError};
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::locale::{get_message, get_message_with_args};
@ -31,6 +33,15 @@ mod options {
#[uucore::main]
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 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)?;
}
// 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() {
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"))),
}

View file

@ -1561,6 +1561,5 @@ fn test_broken_pipe_no_error() {
.args(&["e", "a"])
.pipe_in("hello".repeat(100))
.run_stdout_starts_with(b"")
.success()
.stderr_is("");
.fails_silently();
}