Skip to content

Commit

Permalink
Work around ssh setting stderr to O_NONBLOCK
Browse files Browse the repository at this point in the history
  • Loading branch information
piegamesde committed Feb 3, 2024
1 parent c3c50f5 commit 78bbfc4
Showing 1 changed file with 27 additions and 13 deletions.
40 changes: 27 additions & 13 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -436,11 +436,7 @@ fn cli_to_serve_process(

let mut proc = match std::process::Command::new(bin)
.args(serve_cmd_args)
.stderr(if progress.is_hidden() {
std::process::Stdio::inherit()
} else {
std::process::Stdio::piped()
})
.stderr(std::process::Stdio::piped())
.stdin(std::process::Stdio::piped())
.stdout(std::process::Stdio::piped())
.spawn()
Expand All @@ -449,21 +445,39 @@ fn cli_to_serve_process(
Err(err) => anyhow::bail!("error spawning serve command: {}", err),
};

let stderr_reader = if progress.is_hidden() {
None
} else {
let stderr_reader = {
let progress = progress.clone();
let proc_stderr = proc.stderr.take().unwrap();

let stderr_reader = std::thread::spawn(move || {
let buf_reader = std::io::BufReader::new(proc_stderr);
for line in buf_reader.lines().flatten() {
progress.println(&line);
// Theres a tiny race condition here where we may print an
// error line twice, I can't see how to fix this unless we
// rewrite the progress bar library to report if the print happened.
if progress.is_finished() || progress.is_hidden() {
if progress.is_hidden() {
/*
* Workaround for SSH rogue behavior.
* It sets its file descriptors to O_NONBLOCK, and because these
* are shared on Unix it would also affect our stderr if we simply
* inherited that file descriptor. Instead, we always use `piped` and
* simply read and forward the bytes in a thread.
*
* See also:
* https://github.com/andrewchambers/bupstash/issues/378
* https://public-inbox.org/git/[email protected]/T/
* https://lists.nongnu.org/archive/html/bug-cvs/2005-07/msg00008.html
* https://www.spinics.net/lists/openssh-unix-dev/msg06047.html
* https://github.com/rust-lang/rust/issues/13336
* https://github.com/rust-lang/rust/issues/100673
*/
let _ = writeln!(std::io::stderr(), "{}", line);
} else {
progress.println(&line);

// Theres a tiny race condition here where we may print an
// error line twice, I can't see how to fix this unless we
// rewrite the progress bar library to report if the print happened.
if progress.is_finished() || progress.is_hidden() {
let _ = writeln!(std::io::stderr(), "{}", line);
}
}
}
});
Expand Down

0 comments on commit 78bbfc4

Please sign in to comment.