读取和写入长时间运行的 std::process::Child [英] Reading and writing to a long-running std::process::Child
问题描述
我有一个长时间运行的子进程,我需要读取和写入大量数据.我有一个读取器线程和一个写入器线程分别操作 child.stdout
和 child.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屋!