Rust 通过Tokio UnixStream与子进程通信

Rust 通过Tokio UnixStream与子进程通信,rust,fork,socketpair,tokio,Rust,Fork,Socketpair,Tokio,我试图让父进程和子进程使用Tokio相互通信。问题是,由于某种原因,孩子无法读取父母写入套接字的任何内容(可能是相反的方式) 我的函数类似于下面的 pub async fn run()->结果{ 让mut socks=UnixStream::pair()?; 火柴叉{ Ok(ForkResult::Parent{..})=>{ 袜子。0。写_u32(31337)。等待?; 好(()) } Ok(ForkResult::Child)=>{ eprintln!(“从大师那里读”); 让msg=soc

我试图让父进程和子进程使用Tokio相互通信。问题是,由于某种原因,孩子无法读取父母写入套接字的任何内容(可能是相反的方式)

我的函数类似于下面的

pub async fn run()->结果{
让mut socks=UnixStream::pair()?;
火柴叉{
Ok(ForkResult::Parent{..})=>{
袜子。0。写_u32(31337)。等待?;
好(())
}
Ok(ForkResult::Child)=>{
eprintln!(“从大师那里读”);
让msg=socks.1.读_u32().等待?;
eprintln!(“从主控{}读取”,msg);
好(())
}
Err()=>Err(错误),
}
}
套接字不会关闭,否则我在尝试从
socks.1
读取时会立即出错。如果我将读取移动到父进程中,它将按预期工作。第一行
从master
读取会被打印,但第二行永远不会被调用

我无法更改通信模式,因为我将使用
execve
启动另一个二进制文件,该二进制文件将与
socketpair
进行通信

知道我这里做错了什么吗?这与从
async
函数生成的
async
/
wait
状态机有关吗?

当您调用系统调用时:

子进程是用一个名为fork()的线程创建的

tokio中的默认执行器是线程池执行器。子进程将只获取池中的一个线程,因此无法正常工作

我发现通过将线程池设置为仅包含一个线程,我可以使您的程序正常工作,如下所示:

use tokio::prelude::*;
use tokio::net::UnixStream;
use nix::unistd::{fork, ForkResult};
use nix::sys::wait;
use std::io::Error;
use std::io::ErrorKind;
use wait::wait;

// Limit to 1 thread
#[tokio::main(core_threads = 1)]
async fn main() -> Result<(), Error> {
    let mut socks = UnixStream::pair()?;

    match fork() {
        Ok(ForkResult::Parent { .. }) => {
            eprintln!("Writing!");
            socks.0.write_u32(31337).await?;
            eprintln!("Written!");
            wait().unwrap();
            Ok(())
        }

        Ok(ForkResult::Child) => {
            eprintln!("Reading from master");
            let msg = socks.1.read_u32().await?;
            eprintln!("Read from master {}", msg);
            Ok(())
        }

        Err(_) => Err(Error::new(ErrorKind::Other, "oh no!")),
    }
}
使用东京:前奏曲:*; 使用tokio::net::UnixStream; 使用nix::unistd::{fork,ForkResult}; 使用nix::sys::wait; 使用std::io::Error; 使用std::io::ErrorKind; 使用wait::wait; //限制为1个线程 #[tokio::main(核心线程=1)] 异步fn main()->结果{ 让mut socks=UnixStream::pair()?; 火柴叉{ Ok(ForkResult::Parent{..})=>{ eprintln!(“写作!”); 袜子。0。写_u32(31337)。等待?; eprintln!(“书面的!”); 等待(); 好(()) } Ok(ForkResult::Child)=>{ eprintln!(“从大师那里读”); 让msg=socks.1.读_u32().等待?; eprintln!(“从主控{}读取”,msg); 好(()) } Err()=>Err(Error::new(ErrorKind::Other,“噢,不!”), } } 我必须做的另一个更改是,通过调用
wait()
,强制父对象等待子对象完成—这也是您可能不希望在真正的异步程序中执行的操作

我读到的大多数建议都是,如果需要从线程程序中分叉,可以在创建任何线程之前进行,也可以在分叉后立即在子程序中调用
exec\ve()
(这是您计划要做的)