Как мне прочитать выходные данные дочернего процесса без блокировки в Rust?
Я делаю небольшое приложение ncurses в Rust, которое должно взаимодействовать с дочерним процессом. У меня уже есть прототип, написанный на Common Lisp; подарокВот надеюсь, покажет, что я хочу сделать. Я пытаюсь переписать его, потому что CL использует огромное количество памяти для такого маленького инструмента.
Я раньше не использовал Rust (или другие языки низкого уровня), и у меня возникли проблемы с выяснением того, как взаимодействовать с подпроцессом.
То, что я сейчас делаю, примерно так:
Создайте процесс:
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
это продолжается только после того, как я вручную уничтожаю подпроцесс.
Редактировать:
На основеэтот ответЯ изменил код для использования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
или.