如何创建在 tokio::process::Child 退出而不关闭标准输入的情况下完成的未来
How to create future that completes once tokio::process::Child has exited without closing stdin
如何创建一个在 tokio::process::Child
终止时完成而不关闭 stdin
的未来。我知道有 try_wait
用于测试进程是否在未关闭的情况下终止 stdin
,但我希望这种行为具有未来的语义。
我试图为这个问题准备一个 MRE,我的代码在调用 wait
后由于写入 stdin
而导致崩溃,但我观察到的行为与文档中所述的行为不符对于 tokio::process::Child
的 wait method。我希望看到 stdin.write_u8(24).await.unwrap();
行因管道破裂而崩溃,因为 stdin
应该被 wait
.
关闭
use tokio::{time, io::AsyncWriteExt}; // 1.0.1
use std::time::Duration;
#[tokio::main]
pub async fn main() {
let mut child = tokio::process::Command::new("nano")
.stdin(std::process::Stdio::piped())
.spawn()
.unwrap();
let mut stdin = child.stdin.take().unwrap();
let tasklet = tokio::spawn(async move {
child.wait().await
});
// this delay should give tokio::spawn plenty of time to spin up
// and call `wait` on the child (closing stdin)
time::sleep(Duration::from_millis(1000)).await;
// write character 24 (CANcel, ^X) to stdin to close nano
stdin.write_u8(24).await.unwrap();
match tasklet.await {
Ok(exit_result) => match exit_result {
Ok(exit_status) => eprintln!("exit_status: {}", exit_status),
Err(terminate_error) => eprintln!("terminate_error: {}", terminate_error)
}
Err(join_error) => eprintln!("join_error: {}", join_error)
}
}
所以这个问题的答案是 tokio::process::Child
中的 Option::take
ChildStdin
,如本 Github issue 中所述。在这种情况下,wait
不会关闭 stdin
并且程序员有责任不造成死锁。
上面的 MRE 没有失败有两个原因:(i) 我从 tokio::process::Child
中取出 ChildStdin
和 (ii) 即使我没有取出它,它仍然会尚未关闭,因为代码中的错误将在 this pull request.
中修复
如何创建一个在 tokio::process::Child
终止时完成而不关闭 stdin
的未来。我知道有 try_wait
用于测试进程是否在未关闭的情况下终止 stdin
,但我希望这种行为具有未来的语义。
我试图为这个问题准备一个 MRE,我的代码在调用 wait
后由于写入 stdin
而导致崩溃,但我观察到的行为与文档中所述的行为不符对于 tokio::process::Child
的 wait method。我希望看到 stdin.write_u8(24).await.unwrap();
行因管道破裂而崩溃,因为 stdin
应该被 wait
.
use tokio::{time, io::AsyncWriteExt}; // 1.0.1
use std::time::Duration;
#[tokio::main]
pub async fn main() {
let mut child = tokio::process::Command::new("nano")
.stdin(std::process::Stdio::piped())
.spawn()
.unwrap();
let mut stdin = child.stdin.take().unwrap();
let tasklet = tokio::spawn(async move {
child.wait().await
});
// this delay should give tokio::spawn plenty of time to spin up
// and call `wait` on the child (closing stdin)
time::sleep(Duration::from_millis(1000)).await;
// write character 24 (CANcel, ^X) to stdin to close nano
stdin.write_u8(24).await.unwrap();
match tasklet.await {
Ok(exit_result) => match exit_result {
Ok(exit_status) => eprintln!("exit_status: {}", exit_status),
Err(terminate_error) => eprintln!("terminate_error: {}", terminate_error)
}
Err(join_error) => eprintln!("join_error: {}", join_error)
}
}
所以这个问题的答案是 tokio::process::Child
中的 Option::take
ChildStdin
,如本 Github issue 中所述。在这种情况下,wait
不会关闭 stdin
并且程序员有责任不造成死锁。
上面的 MRE 没有失败有两个原因:(i) 我从 tokio::process::Child
中取出 ChildStdin
和 (ii) 即使我没有取出它,它仍然会尚未关闭,因为代码中的错误将在 this pull request.