运行多个控制台时标准输入冲突

问题描述 投票:0回答:1

以下代码(为

windows
编译)迭代地从控制台请求命令。

如果命令是

exit
,则迭代(和程序)终止; 如果命令是
new_console
,则打开一个新控制台,其中包含程序的新实例,并且迭代继续; 否则,迭代将继续并显示错误消息。

因此,如果我在第一个实例中输入

new_console
,我应该会得到两个控制台,我可以在其中输入命令并与每个程序实例交互。

一切都像这样工作,除了我只能在一个控制台上输入命令,并且该控制台在每个命令后随机更改。

因此,我怀疑控制台的

stdin
是冲突的。

如何避免这种情况?

fn main() -> std::io::Result<()> { 
    use std::process::Command;
    use std::os::windows::process::CommandExt;
    let mut args = std::env::args();
    let command_self = args.next().unwrap();
    let mut childs = Vec::new();
    let mut loop_on = true;
    let mut stdin_lines = std::io::stdin().lines();
    while loop_on {
        println!("Enter line:");
        let entry = match stdin_lines.next() {
            None => break, Some(r) => r,
        }?;
        match entry.as_str() {
            "exit" => loop_on = false,
            "new_console" => {
                childs.push({
                    Command::new(&command_self)
                            .creation_flags(0x00000410)
                            .spawn()
                            .expect("failed to execute process")
                });                            
            },
            c => {
                println!("unknown command: {c}");
            },
        }    
    }
    childs.into_iter().for_each(|mut c| { let _ = c.wait(); } );
    Ok(())
}

windows rust command
1个回答
0
投票

虽然我不太熟悉 Windows 上句柄的细节,但我可以说这在 Unix 上是预料之中的。当您生成新进程时,除非您指定新的输入源,否则文件描述符将被继承,并且新旧进程共享完全相同的文件描述。因此,当您提供输入时,它将仅由一个进程读取,而哪个进程没有明确定义。

一般来说,除非您知道自己在做什么,否则您不希望两个程序尝试从同一文件描述符(Windows 上的句柄)读取。如果您的目标是让新程序从标准输入读取,那么您应该通过执行以下操作来等待命令退出:

let child = Command::new(&command_self)
                .creation_flags(0x00000410)
                .spawn()
                .expect("failed to execute process");
let _ = child.wait();

这将有效地导致父进程等待子进程退出,因此父进程“不会”做的是尝试读取标准输入。一旦子进程退出,父进程将恢复循环并正常进行。 在 Unix 上,您还可以在

exec

上调用

Command
而不是
spawn
,这会将当前进程完全替换为新进程,这意味着旧进程将不再存在(已被替换),因此不再尝试从标准输入读取。然而,虽然这样的功能在 Windows 上是可能的(毕竟,Cygwin 实现了它),但它并不简单,并且不包含在 Rust 标准库中。
    

© www.soinside.com 2019 - 2024. All rights reserved.