读取和写入长时间运行的 std::process::Child [英] Reading and writing to a long-running std::process::Child

查看:48
本文介绍了读取和写入长时间运行的 std::process::Child的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have a long-running child process to which I need to read and write a lot of data. I have a reader thread and a writer thread that manipulate the child.stdout and child.stdin respectively:

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???
        });
    });
}

编写器完成后,我想关闭 child_stdin 以便子进程完成并退出,以便读者看到 EOF 和 pool.scoped 返回.没有 child.wait() 我不能这样做,我不能调用 child.wait() 因为它被两个线程借用了.

When the writer is done, I want to close child_stdin so that the subprocess finishes and exits, so that the reader sees EOF and pool.scoped returns. I can't do this without child.wait() and I can't call child.wait() because it's being borrowed by the two threads.

我如何使这个程序完整?

How do I make this program complete?

推荐答案

有趣的是,这是您通过使用 Mutex ^_^ 共享所有权而自己造成的.不要引用对 child.stdin 的引用,而是获取它的完整所有权并将其传递给线程.当线程结束时,它会被丢弃,隐式关闭它:

Amusingly, you've caused this yourself by sharing ownership using the Mutex ^_^. Instead of taking a reference to child.stdin, take complete ownership of it and pass it to the thread. When the thread is over, it will be dropped, closing it implicitly:

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.
);

如果您仍然希望能够调用 wait 以获取 ExitStatus,请更改对 stdout 的引用并传输stdin 的所有权以使用 Option::take.这意味着 child 根本没有被借用:

If you'd like to still be able to call wait to get the ExitStatus, change the reference to stdout and the transfer of ownership of stdin to use Option::take. This means that child is not borrowed at all:

let mut child = // ...

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

// ...

child.wait().unwrap();

这篇关于读取和写入长时间运行的 std::process::Child的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆