1
Fork 0
mirror of https://github.com/RGBCube/uutils-coreutils synced 2025-07-28 19:47:45 +00:00

Merge pull request #7273 from RenjiSann/tee-fix-p-broken-stdout

tee: fix -p behavior upon broken pipe stdout
This commit is contained in:
Daniel Hofstetter 2025-02-07 16:19:18 +01:00 committed by GitHub
commit 03b6371422
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 131 additions and 28 deletions

View file

@ -165,6 +165,7 @@ mod linux_only {
use std::fmt::Write;
use std::fs::File;
use std::process::{Output, Stdio};
use std::time::Duration;
fn make_broken_pipe() -> File {
use libc::c_int;
@ -183,6 +184,22 @@ mod linux_only {
unsafe { File::from_raw_fd(fds[1]) }
}
fn make_hanging_read() -> File {
use libc::c_int;
use std::os::unix::io::FromRawFd;
let mut fds: [c_int; 2] = [0, 0];
assert!(
(unsafe { libc::pipe(std::ptr::from_mut::<c_int>(&mut fds[0])) } == 0),
"Failed to create pipe"
);
// PURPOSELY leak the write end of the pipe, so the read end hangs.
// Return the read end of the pipe
unsafe { File::from_raw_fd(fds[0]) }
}
fn run_tee(proc: &mut UCommand) -> (String, Output) {
let content = (1..=100_000).fold(String::new(), |mut output, x| {
let _ = writeln!(output, "{x}");
@ -535,4 +552,31 @@ mod linux_only {
expect_failure(&output, "No space left");
expect_short(file_out_a, &at, content.as_str());
}
#[test]
fn test_pipe_mode_broken_pipe_only() {
new_ucmd!()
.timeout(Duration::from_secs(1))
.arg("-p")
.set_stdin(make_hanging_read())
.set_stdout(make_broken_pipe())
.succeeds();
}
#[test]
fn test_pipe_mode_broken_pipe_file() {
let (at, mut ucmd) = at_and_ucmd!();
let file_out_a = "tee_file_out_a";
let proc = ucmd
.arg("-p")
.arg(file_out_a)
.set_stdout(make_broken_pipe());
let (content, output) = run_tee(proc);
expect_success(&output);
expect_correct(file_out_a, &at, content.as_str());
}
}