oconnor663 / duct.rs

a Rust library for running child processes
MIT License
795 stars 34 forks source link

Problem with incremental output?! #103

Closed manfredlotz closed 2 years ago

manfredlotz commented 2 years ago

I am playing with duct and get a problem where I am not sure if the problem does exist between my keyboard and chair.

Looking at an example on the duct crate page I try this

use duct::cmd;
use std::io::prelude::*;
use std::io::BufReader;

fn big_command(big_cmd: &str) {
    let big_cmd = cmd!("bash", "-c", big_cmd);
    let reader = big_cmd.stderr_to_stdout().reader().unwrap();
    let lines = BufReader::new(reader).lines();
    for line in lines {
        match line {
            Ok(out) => println!("{out}"),
            Err(e) => println!("Err: {e}")
        }
    }

}

fn main() {
    big_command("notfoundcmd 1>&2");
}

and get this line ad infinitum

Err: command ["bash", "-c", "notfoundcmd 1>&2"] exited with code 127
oconnor663 commented 2 years ago

I believe this is expected. Take a look at the docs for ReaderHandle (the thing returned by .reader()). Here's the important part:

When this reader reaches EOF, it automatically calls wait on the inner handle. If the child returns a non-zero exit status, the read at EOF will return an error, unless you use unchecked.

That's what's happening here. Your Bash child process returns a non-zero exit status, because notfoundcmd isn't found. So after reading EOF from the Bash process's output pipe (which happens immediately because Bash writes nothing to stdout), Duct waits on Bash, finds that it's exited with a non-zero status, and returns an error. If you keep reading in a loop, as you do here, you will keep getting that same error over and over forever.

My recommendation would be to make sure that the Err(e) branch breaks out of your read loop or panics or something like that. Any error that comes up there is unlikely to be recoverable. I think the same would be true in other situations like reading from a network socket, where if you get "error connection closed" once, you're going to keep getting it every time if you keep reading.

manfredlotz commented 2 years ago

Thanks a lot for the background. So, indeed I will break out of the read loop.