无法在 Rust 中读取子 stderr 两次

Unable to read child stderr twice in Rust

出于某种原因,我无法第二次从子进程中读取 stderr。这就是我所做的。

我正在生成用于黄瓜测试的子进程。在第一步中,我生成了进程,获取它的 stderr,保存它,然后从中读取。这是代码:

pub fn wait_process_output(
    reader: &mut BufReader<ChildStderr>,
    output: Vec<(String, u16)>,
) -> Result<(), String> {
    let mut process_output = String::new();
    loop {
        match reader.read_line(&mut process_output) {
            Err(e) => {
                return Err(format!("Unable to read output: {}", e));
            }
            Ok(_) => {
                // processing here
            }
        };
    }
}

pub fn step1(world: &mut TestWorld) {
    world.app_handler = Some(
        Command::new(&world.app_bin)
            .stderr(Stdio::piped())
            .spawn()
            .unwrap(),
    );
    let app_stderr = world.app_handler.as_mut().unwrap().stderr.take().unwrap();
    world.app_reader = Some(BufReader::new(app_stderr));
    wait_process_output(world.app_reader.as_mut().unwrap(), /* expected data */).ok();
}

此代码工作正常:stderr 正在按预期读取。

在第三个测试步骤中,我尝试再次读取进程输出:

pub fn step3(world: &mut TestWorld) {
    wait_process_output(world.app_reader.as_mut().unwrap(), /* expected data */).ok();
}

这次 reader.read_line 无限挂起:没有任何内容被读取。我确定子进程会产生一些输出:如果我 运行 在相同的条件下分别看到它。

当我第二次尝试读取时,为什么 BufReader 对象会损坏,您能否提出任何想法?

我得到了解决方案。问题是 appstep3 开始读取它之前产生了输出。我以为针对这种情况实施了某种缓冲区,但看来我错了。所以我最终使用了以下两种方法来解决我的问题:

pub fn wait_process_output(
    receiver: &Receiver<String>,
    output: Vec<(String, u16)>,
) -> Result<(), String> {
    loop {
        match receiver.try_recv() {
            // process output
        }
    }
}

pub fn start_listener(sender: Sender<String>, stream: ChildStderr) {
    spawn(move || {
        let mut f = BufReader::new(stream);
        loop {
            let mut buf = String::new();
            match f.read_line(&mut buf) {
                Ok(_) => {
                    sender.send(buf).unwrap();
                    continue;
                }
                Err(e) => {
                    println!("Unable to read process stderr: {:?}", e);
                    break;
                }
            }
        }
    });
}