读取和写入长时间运行的 std::process::Child

nja*_*ard 6 rust

我有一个长时间运行的子进程,我需要读取和写入大量数据。我有一个读取器线程和一个写入器线程,分别操作child.stdoutchild.stdin

extern crate scoped_threadpool;

fn main() {
    // run the subprocess
    let mut child = std::process::Command::new("cat")
        .stdin(std::process::Stdio::piped())
        .stdout(std::process::Stdio::piped())
        .spawn()
        .unwrap();

    let child_stdout = child.stdout.as_mut().unwrap();
    let child_stdin = std::sync::Mutex::new(child.stdin.as_mut().unwrap());

    let mut pool = scoped_threadpool::Pool::new(2);
    pool.scoped(|scope| {
        // read all output from the subprocess
        scope.execute(move || {
            use std::io::BufRead;
            let reader = std::io::BufReader::new(child_stdout);
            for line in reader.lines() {
                println!("{}", line.unwrap());
            }
        });

        // write to the subprocess
        scope.execute(move || {
            for a in 0..1000 {
                use std::io::Write;
                writeln!(&mut child_stdin.lock().unwrap(), "{}", a).unwrap();
            } // close child_stdin???
        });
    });
}
Run Code Online (Sandbox Code Playgroud)

当编写器完成后,我想关闭child_stdin以便子进程完成并退出,以便读者看到 EOF 并pool.scoped返回。如果没有,我就无法执行此操作child.wait(),也无法调用child.wait(),因为它被两个线程借用。

我怎样才能完成这个程序?

She*_*ter 4

有趣的是,您自己通过使用Mutex^_^ 共享所有权而导致了这种情况。不要引用child.stdin,而是获取它的完全所有权并将其传递给线程。当线程结束时,它将被删除,并隐式关闭它:

let mut child_stdin = child.stdin.unwrap();

// ...

scope.execute(move ||
    for a in 0..1000 {
        use std::io::Write;
        writeln!(&mut child_stdin, "{}", a).unwrap();
    }
    // child_stdin has been moved into this closure and is now
    // dropped, closing it.
);
Run Code Online (Sandbox Code Playgroud)

如果您仍希望能够调用wait来获取ExitStatus,请将引用stdout和所有权转移更改stdin为使用Option::take。这意味着child根本没有借用:

let mut child = // ...

let child_stdout = child.stdout.as_mut().unwrap();
let mut child_stdin = child.stdin.take().unwrap();

// ...

child.wait().unwrap();
Run Code Online (Sandbox Code Playgroud)

  • @njaard 你*想*在哪里调用`child.wait()`? (2认同)