From a9644a6d61063d2b14bf05bec608bd1284bb9740 Mon Sep 17 00:00:00 2001 From: OneNoted Date: Wed, 15 Apr 2026 11:31:10 +0200 Subject: [PATCH] fix: prefer child exit status over clipboard broken pipe Normalize the clipboard error path so an early child exit that closes stdin reports the child's non-zero status when available instead of racing into a less useful broken-pipe error. Constraint: Success-path clipboard writes must keep failing fast on real stdin write errors Rejected: Keep treating every broken pipe as the primary failure | hides the child's actual non-zero exit in CI Confidence: high Scope-risk: narrow Reversibility: clean Directive: When a child process can exit before stdin is fully written, prefer the final process status if it explains the failure more accurately Tested: cargo test inject::tests:: -- --nocapture; cargo fmt --all -- --check; cargo check --all-targets; cargo clippy --all-targets -- -D warnings; cargo test Not-tested: GitHub Actions rerun still pending --- src/inject/clipboard.rs | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/src/inject/clipboard.rs b/src/inject/clipboard.rs index e9a7906..93a8a5e 100644 --- a/src/inject/clipboard.rs +++ b/src/inject/clipboard.rs @@ -46,15 +46,23 @@ pub(super) fn run_wl_copy_with_timeout( .spawn() .map_err(|e| WhsprError::Injection(format!("failed to spawn wl-copy: {e}")))?; + let mut saw_broken_pipe = false; { use std::io::Write; let mut stdin = wl_copy .stdin .take() .ok_or_else(|| WhsprError::Injection("wl-copy stdin unavailable".into()))?; - stdin - .write_all(text.as_bytes()) - .map_err(|e| WhsprError::Injection(format!("wl-copy stdin write: {e}")))?; + if let Err(err) = stdin.write_all(text.as_bytes()) { + if err.kind() == std::io::ErrorKind::BrokenPipe { + saw_broken_pipe = true; + } else { + return Err(WhsprError::Injection(format!( + "wl-copy stdin write: {e}", + e = err + ))); + } + } } let deadline = std::time::Instant::now() + timeout; @@ -80,5 +88,10 @@ pub(super) fn run_wl_copy_with_timeout( "wl-copy exited with {status}" ))); } + if saw_broken_pipe { + return Err(WhsprError::Injection( + "wl-copy closed stdin before consuming the clipboard payload".into(), + )); + } Ok(()) }