【发布时间】:2016-04-09 06:44:52
【问题描述】:
我正在 Rust 中制作一个需要与子进程通信的小型 ncurses 应用程序。我已经有一个用 Common Lisp 编写的原型。我正在尝试重写它,因为 CL 为这么小的工具使用了大量的内存。
我在弄清楚如何与子流程交互时遇到了一些麻烦。
我现在做的大致是这样的:
-
创建流程:
let mut program = match Command::new(command) .args(arguments) .stdin(Stdio::piped()) .stdout(Stdio::piped()) .stderr(Stdio::piped()) .spawn() { Ok(child) => child, Err(_) => { println!("Cannot run program '{}'.", command); return; } }; -
将它传递给一个无限循环(直到用户退出),该循环像这样读取和处理输入并监听输出(并将其写入屏幕):
fn listen_for_output(program: &mut Child, output_viewer: &TextViewer) { match program.stdout { Some(ref mut out) => { let mut buf_string = String::new(); match out.read_to_string(&mut buf_string) { Ok(_) => output_viewer.append_string(buf_string), Err(_) => return, }; } None => return, }; }
对read_to_string 的调用会阻塞程序直到进程退出。从我可以看到read_to_end 和read 似乎也被阻止了。如果我尝试运行像 ls 这样的东西,它会立即退出,它可以工作,但是对于像 python 或 sbcl 这样不会退出的东西,它只有在我手动终止子进程后才会继续。
基于this answer,我将代码改为使用BufReader:
fn listen_for_output(program: &mut Child, output_viewer: &TextViewer) {
match program.stdout.as_mut() {
Some(out) => {
let buf_reader = BufReader::new(out);
for line in buf_reader.lines() {
match line {
Ok(l) => {
output_viewer.append_string(l);
}
Err(_) => return,
};
}
}
None => return,
}
}
但是,问题仍然存在。它将读取所有可用的行,然后阻塞。由于该工具应该适用于任何程序,因此在尝试读取之前无法猜测输出何时结束。似乎也没有办法为BufReader 设置超时。
【问题讨论】:
标签: process io rust blocking pty