-
Notifications
You must be signed in to change notification settings - Fork 13
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Stream output while subprocess is running (#43)
* Add a simple proof-of-concept of the output streaming pattern suggested in https://stackoverflow.com/a/72862682/113632 * Implement streaming support for subprocess output. As suggested in https://stackoverflow.com/q/66060139 the child process' streams are processed in background threads responsible for both persisting and streaming the output to the caller's stdout/stderr. Scoped threads are used to support streaming to references such as `&mut Vec<u8>` and to loosen the type requirements of the stream (namely to not require that they are 'static). CLI: * Subprocess out/err streams are duplicated to bkt's out/err while the subprocess runs, instead of caching all output first and then writing the cached output after the subprocess completes. * Streaming is enabled by default and is not configurable. Library: * Added `Bkt::retrieve_streaming` and `Bkt::refresh_streaming` methods which accept out/err sinks. The subprocess' output is written to these streams in addition to being cached and available in the returned `Invocation`. * These methods are marked "experimental" and are subject to change or even removal.
- Loading branch information
Showing
5 changed files
with
349 additions
and
39 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
// Demo of streaming the out/err of a subprocess as it executes. | ||
// See also https://stackoverflow.com/a/72862682/113632 and #31 | ||
|
||
use std::io::{Read, Write}; | ||
use std::process::{Command, Stdio}; | ||
|
||
static BASH_CMD: &str = | ||
"echo START; date >&2 | ||
sleep 1 | ||
printf MID | ||
sleep 1 | ||
echo DLE; date >&2 | ||
sleep 3 | ||
echo DONE; date >&2"; | ||
|
||
fn stream( | ||
mut source: impl Read, | ||
mut sink: impl Write, | ||
) -> std::io::Result<()> { | ||
// This initialization can be avoided (safely) once | ||
// https://github.com/rust-lang/rust/issues/78485 is stable. | ||
let mut buf = [0u8; 1024]; | ||
loop { | ||
let num_read = source.read(&mut buf)?; | ||
if num_read == 0 { | ||
break; | ||
} | ||
|
||
let buf = &buf[..num_read]; | ||
sink.write_all(buf)?; | ||
// flush is needed to print partial lines, otherwise output is buffered until a newline | ||
sink.flush()?; | ||
} | ||
|
||
Ok(()) | ||
} | ||
|
||
fn main() { | ||
let mut child = Command::new("bash").args(&["-c", BASH_CMD]) | ||
.stdout(Stdio::piped()) | ||
.stderr(Stdio::piped()) | ||
.spawn() | ||
.expect("failed to execute child"); | ||
|
||
let child_out = child.stdout.take().expect("cannot attach to child stdout"); | ||
let child_err = child.stderr.take().expect("cannot attach to child stderr"); | ||
|
||
let thread_out = std::thread::spawn(move || { | ||
stream(child_out, std::io::stdout()) | ||
.expect("error communicating with child stdout") | ||
}); | ||
let thread_err = std::thread::spawn(move || { | ||
stream(child_err, std::io::stderr()).expect("error communicating with child stderr") | ||
}); | ||
|
||
thread_out.join().expect("child stdout thread failed to join"); | ||
thread_err.join().expect("child stderr thread failed to join"); | ||
|
||
let status = child.wait().expect("Subprocess wait failed"); | ||
assert!(status.success(), "Subprocess failed"); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.