Когда вы вызываете системный вызов fork () :
Дочерний процесс создается с одним потоком - тот, который вызвал 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!")),
}
}
Еще одно изменение, которое я должен был сделать, - заставить родителя ждать завершения работы ребенка, вызвав wait()
- то, что вы, вероятно, не хотите делать в реальном asyn c program.
Большинство прочитанных мною советов, что если вам нужно разветвиться из многопоточной программы, сделайте это перед созданием каких-либо потоков или вызовите exec_ve()
в потомке сразу после разветвления ( что ты планируешь делать в любом случае).