From e3c3d443584b629803a73ad66e0e298943c7f201 Mon Sep 17 00:00:00 2001 From: akbash Date: Wed, 19 Aug 2026 20:39:24 +0300 Subject: fix(cli): exit quietly when output pipes close (#2996) refs #2994 Co-authored-by: akbash-bot <300245827+akbash-bot@users.noreply.github.com> --- tests/broken_pipe.rs | 49 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) create mode 100644 tests/broken_pipe.rs (limited to 'tests') diff --git a/tests/broken_pipe.rs b/tests/broken_pipe.rs new file mode 100644 index 00000000..66aa029e --- /dev/null +++ b/tests/broken_pipe.rs @@ -0,0 +1,49 @@ +#![cfg(unix)] + +use std::os::fd::{FromRawFd, OwnedFd}; +use std::os::unix::process::ExitStatusExt; +use std::process::{Command, Output, Stdio}; + +fn closed_pipe_writer() -> Stdio { + let mut fds = [-1; 2]; + assert_eq!(unsafe { libc::pipe(fds.as_mut_ptr()) }, 0); + // SAFETY: pipe initialized both descriptors, and each is assigned to one + // OwnedFd so it is closed exactly once. + let read_fd = unsafe { OwnedFd::from_raw_fd(fds[0]) }; + let write_fd = unsafe { OwnedFd::from_raw_fd(fds[1]) }; + drop(read_fd); + Stdio::from(write_fd) +} + +fn run_with_closed_stdout(args: &[&str]) -> Output { + Command::new(env!("CARGO_BIN_EXE_herdr")) + .args(args) + .stdout(closed_pipe_writer()) + .stderr(Stdio::piped()) + .output() + .expect("run herdr CLI") +} + +fn assert_quiet_sigpipe(output: Output) { + assert_eq!(output.status.signal(), Some(libc::SIGPIPE)); + assert!( + output.stderr.is_empty(), + "closed stdout should not emit an error or panic: {}", + String::from_utf8_lossy(&output.stderr) + ); +} + +#[test] +fn cli_exits_via_sigpipe_without_panicking_when_stdout_closes() { + assert_quiet_sigpipe(run_with_closed_stdout(&["api", "schema", "--json"])); +} + +#[test] +fn terminal_help_uses_cli_sigpipe_behavior_before_attach_starts() { + assert_quiet_sigpipe(run_with_closed_stdout(&["terminal", "attach", "--help"])); +} + +#[test] +fn completion_direct_writer_uses_cli_sigpipe_behavior() { + assert_quiet_sigpipe(run_with_closed_stdout(&["completion", "bash"])); +} -- cgit v1.2.3