Skip to content

Commit 4c6a711

Browse files
committed
uucore: centralize SIGPIPE handling in main macro
1 parent 425b232 commit 4c6a711

12 files changed

Lines changed: 44 additions & 54 deletions

File tree

src/uu/cat/src/cat.rs

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -218,13 +218,6 @@ mod options {
218218

219219
#[uucore::main]
220220
pub fn uumain(args: impl uucore::Args) -> UResult<()> {
221-
// When we receive a SIGPIPE signal, we want to terminate the process so
222-
// that we don't print any error messages to stderr. Rust ignores SIGPIPE
223-
// (see https://github.com/rust-lang/rust/issues/62569), so we restore it's
224-
// default action here.
225-
#[cfg(not(target_os = "windows"))]
226-
let _ = uucore::signals::enable_pipe_errors();
227-
228221
let matches = uucore::clap_localization::handle_clap_result(uu_app(), args)?;
229222

230223
let number_mode = if matches.get_flag(options::NUMBER_NONBLANK) {

src/uu/env/src/env.rs

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1095,10 +1095,6 @@ fn list_signal_handling(log: &SignalActionLog) {
10951095

10961096
#[uucore::main]
10971097
pub fn uumain(args: impl uucore::Args) -> UResult<()> {
1098-
// Rust ignores SIGPIPE (see https://github.com/rust-lang/rust/issues/62569).
1099-
// We restore its default action here.
1100-
#[cfg(unix)]
1101-
let _ = uucore::signals::enable_pipe_errors();
11021098
EnvAppData::default().run_env(args)
11031099
}
11041100

src/uu/seq/src/seq.rs

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -92,22 +92,8 @@ fn select_precision(
9292
}
9393
}
9494

95-
// Initialize SIGPIPE state capture at process startup (Unix only)
96-
#[cfg(unix)]
97-
uucore::init_sigpipe_capture!();
98-
9995
#[uucore::main]
10096
pub fn uumain(args: impl uucore::Args) -> UResult<()> {
101-
// Restore SIGPIPE to default if it wasn't explicitly ignored by parent.
102-
// The Rust runtime ignores SIGPIPE, but we need to respect the parent's
103-
// signal disposition for proper pipeline behavior (GNU compatibility).
104-
#[cfg(unix)]
105-
if !signals::sigpipe_was_ignored() {
106-
// Ignore the return value: if setting signal handler fails, we continue anyway.
107-
// The worst case is we don't get proper SIGPIPE behavior, but seq will still work.
108-
let _ = signals::enable_pipe_errors();
109-
}
110-
11197
let matches =
11298
uucore::clap_localization::handle_clap_result(uu_app(), split_short_args_with_value(args))?;
11399

src/uu/split/src/split.rs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,16 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
5454
let matches = uucore::clap_localization::handle_clap_result(uu_app(), args)?;
5555

5656
match Settings::from(&matches, obs_lines.as_deref()) {
57-
Ok(settings) => split(&settings),
57+
Ok(settings) => {
58+
// When using --filter, we write to a child process's stdin which may
59+
// close early. Disable SIGPIPE so we get EPIPE errors instead of
60+
// being terminated, allowing graceful handling of broken pipes.
61+
#[cfg(unix)]
62+
if settings.filter.is_some() {
63+
let _ = uucore::signals::disable_pipe_errors();
64+
}
65+
split(&settings)
66+
}
5867
Err(e) if e.requires_usage() => Err(UUsageError::new(1, format!("{e}"))),
5968
Err(e) => Err(USimpleError::new(1, format!("{e}"))),
6069
}

src/uu/tail/src/tail.rs

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -40,13 +40,6 @@ use uucore::{show, show_error};
4040

4141
#[uucore::main]
4242
pub fn uumain(args: impl uucore::Args) -> UResult<()> {
43-
// When we receive a SIGPIPE signal, we want to terminate the process so
44-
// that we don't print any error messages to stderr. Rust ignores SIGPIPE
45-
// (see https://github.com/rust-lang/rust/issues/62569), so we restore it's
46-
// default action here.
47-
#[cfg(not(target_os = "windows"))]
48-
let _ = uucore::signals::enable_pipe_errors();
49-
5043
let settings = parse_args(args)?;
5144

5245
settings.check_warnings();

src/uu/tee/src/tee.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ use uucore::{format_usage, show_error};
1919
#[cfg(target_os = "linux")]
2020
use uucore::signals::ensure_stdout_not_broken;
2121
#[cfg(unix)]
22-
use uucore::signals::{enable_pipe_errors, ignore_interrupts};
22+
use uucore::signals::{disable_pipe_errors, ignore_interrupts};
2323

2424
mod options {
2525
pub const APPEND: &str = "append";
@@ -163,8 +163,8 @@ fn tee(options: &Options) -> Result<()> {
163163
if options.ignore_interrupts {
164164
ignore_interrupts().map_err(|_| Error::from(ErrorKind::Other))?;
165165
}
166-
if options.output_error.is_none() {
167-
enable_pipe_errors().map_err(|_| Error::from(ErrorKind::Other))?;
166+
if options.output_error.is_some() {
167+
disable_pipe_errors().map_err(|_| Error::from(ErrorKind::Other))?;
168168
}
169169
}
170170
let mut writers: Vec<NamedWriter> = options

src/uu/timeout/src/timeout.rs

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,6 @@ use uucore::parser::parse_time;
1919
use uucore::process::ChildExt;
2020
use uucore::translate;
2121

22-
#[cfg(unix)]
23-
use uucore::signals::enable_pipe_errors;
24-
2522
use uucore::{
2623
format_usage, show_error,
2724
signals::{signal_by_name_or_value, signal_name_by_value},
@@ -331,8 +328,6 @@ fn timeout(
331328
if !foreground {
332329
let _ = setpgid(Pid::from_raw(0), Pid::from_raw(0));
333330
}
334-
#[cfg(unix)]
335-
enable_pipe_errors()?;
336331

337332
let process = &mut process::Command::new(&cmd[0])
338333
.args(&cmd[1..])

src/uu/tr/src/tr.rs

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -31,13 +31,6 @@ mod options {
3131

3232
#[uucore::main]
3333
pub fn uumain(args: impl uucore::Args) -> UResult<()> {
34-
// When we receive a SIGPIPE signal, we want to terminate the process so
35-
// that we don't print any error messages to stderr. Rust ignores SIGPIPE
36-
// (see https://github.com/rust-lang/rust/issues/62569), so we restore it's
37-
// default action here.
38-
#[cfg(not(target_os = "windows"))]
39-
let _ = uucore::signals::enable_pipe_errors();
40-
4134
let matches = uucore::clap_localization::handle_clap_result(uu_app(), args)?;
4235

4336
let delete_flag = matches.get_flag(options::DELETE);

src/uu/yes/src/yes.rs

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,6 @@ use std::ffi::OsString;
1111
use std::io::{self, Write};
1212
use uucore::error::{UResult, USimpleError};
1313
use uucore::format_usage;
14-
#[cfg(unix)]
15-
use uucore::signals::enable_pipe_errors;
1614
use uucore::translate;
1715

1816
// it's possible that using a smaller or larger buffer might provide better performance on some
@@ -113,8 +111,6 @@ fn prepare_buffer(buf: &mut Vec<u8>) {
113111
pub fn exec(bytes: &[u8]) -> io::Result<()> {
114112
let stdout = io::stdout();
115113
let mut stdout = stdout.lock();
116-
#[cfg(unix)]
117-
enable_pipe_errors()?;
118114

119115
loop {
120116
stdout.write_all(bytes)?;

src/uucore/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,7 @@ windows-sys = { workspace = true, optional = true, default-features = false, fea
119119
utmp-classic = { workspace = true, optional = true }
120120

121121
[features]
122-
default = []
122+
default = ["signals"]
123123
# * non-default features
124124
backup-control = []
125125
colors = []

0 commit comments

Comments
 (0)