mirror of
https://github.com/RGBCube/uutils-coreutils
synced 2025-07-28 03:27:44 +00:00
Do not trap pipe errors in yes
This is part of fixing the tee tests. 'yes' is used by the GNU test suite to identify what the SIGPIPE exit code is on the target platform. By trapping SIGPIPE, it creates a requirement that other utilities also trap SIGPIPE (and exit 0 after SIGPIPE). This is sometimes at odds with their desired behaviour.
This commit is contained in:
parent
7a961a94a5
commit
5c13e88f8b
4 changed files with 35 additions and 2 deletions
1
Cargo.lock
generated
1
Cargo.lock
generated
|
@ -3096,6 +3096,7 @@ name = "uu_yes"
|
|||
version = "0.0.14"
|
||||
dependencies = [
|
||||
"clap 3.1.18",
|
||||
"libc",
|
||||
"nix",
|
||||
"uucore",
|
||||
]
|
||||
|
|
|
@ -16,6 +16,7 @@ path = "src/yes.rs"
|
|||
|
||||
[dependencies]
|
||||
clap = { version = "3.1", features = ["wrap_help", "cargo"] }
|
||||
libc = "0.2.126"
|
||||
uucore = { version=">=0.0.11", package="uucore", path="../../uucore", features=["pipes"] }
|
||||
|
||||
[target.'cfg(any(target_os = "linux", target_os = "android"))'.dependencies]
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
/* last synced with: yes (GNU coreutils) 8.13 */
|
||||
|
||||
use std::borrow::Cow;
|
||||
use std::io::{self, Write};
|
||||
use std::io::{self, Result, Write};
|
||||
|
||||
#[macro_use]
|
||||
extern crate clap;
|
||||
|
@ -70,10 +70,27 @@ fn prepare_buffer<'a>(input: &'a str, buffer: &'a mut [u8; BUF_SIZE]) -> &'a [u8
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(unix)]
|
||||
fn enable_pipe_errors() -> Result<()> {
|
||||
let ret = unsafe { libc::signal(libc::SIGPIPE, libc::SIG_DFL) };
|
||||
if ret == libc::SIG_ERR {
|
||||
return Err(io::Error::new(io::ErrorKind::Other, ""));
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[cfg(not(unix))]
|
||||
fn enable_pipe_errors() -> Result<()> {
|
||||
// Do nothing.
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn exec(bytes: &[u8]) -> io::Result<()> {
|
||||
let stdout = io::stdout();
|
||||
let mut stdout = stdout.lock();
|
||||
|
||||
enable_pipe_errors()?;
|
||||
|
||||
#[cfg(any(target_os = "linux", target_os = "android"))]
|
||||
{
|
||||
match splice::splice_data(bytes, &stdout) {
|
||||
|
|
|
@ -1,7 +1,21 @@
|
|||
use std::io::Read;
|
||||
use std::process::ExitStatus;
|
||||
|
||||
#[cfg(unix)]
|
||||
use std::os::unix::process::ExitStatusExt;
|
||||
|
||||
use crate::common::util::*;
|
||||
|
||||
#[cfg(unix)]
|
||||
fn check_termination(result: &ExitStatus) {
|
||||
assert_eq!(result.signal(), Some(libc::SIGPIPE as i32));
|
||||
}
|
||||
|
||||
#[cfg(not(unix))]
|
||||
fn check_termination(result: &ExitStatus) {
|
||||
assert!(result.success(), "yes did not exit successfully");
|
||||
}
|
||||
|
||||
/// Run `yes`, capture some of the output, close the pipe, and verify it.
|
||||
fn run(args: &[&str], expected: &[u8]) {
|
||||
let mut cmd = new_ucmd!();
|
||||
|
@ -10,7 +24,7 @@ fn run(args: &[&str], expected: &[u8]) {
|
|||
let mut buf = vec![0; expected.len()];
|
||||
stdout.read_exact(&mut buf).unwrap();
|
||||
drop(stdout);
|
||||
assert!(child.wait().unwrap().success());
|
||||
check_termination(&child.wait().unwrap());
|
||||
assert_eq!(buf.as_slice(), expected);
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue