I'm trying to get a parent process and a child process to communicate with each other using a tokio::net::UnixStream. For some reason the child is unable to read whatever the parent writes to the socket, and presumably the other way around.
The function I have is similar to the following:
pub async fn run() -> Result<(), Error> {
    let mut socks = UnixStream::pair()?;
    match fork() {
        Ok(ForkResult::Parent { .. }) => {
            socks.0.write_u32(31337).await?;
            Ok(())
        }
        Ok(ForkResult::Child) => {
            eprintln!("Reading from master");
            let msg = socks.1.read_u32().await?;
            eprintln!("Read from master {}", msg);
            Ok(())
        }
        Err(_) => Err(Error),
    }
}
The socket doesn't get closed, otherwise I'd get an immediate error trying to read from socks.1. If I move the read into the parent process it works as expected. The first line "Reading from master" gets printed, but the second line never gets called.
I cannot change the communication paradigm, since I'll be using execve to start another binary that expects to be talking to a socketpair.
Any idea what I'm doing wrong here? Is it something to do with the async/await?
                        
When you call the fork() system call:
The default executor in tokio is a thread pool executor. The child process will only get one of the threads in the pool, so it won't work properly.
I found I was able to make your program work by setting the thread pool to contain only a single thread, like this:
Another change I had to make was to force the parent to wait for the child to complete, by calling
wait()- also something you probably do not want to be doing in a real async program.Most of the advice I have read that if you need to fork from a threaded program, either do it before creating any threads, or call
exec_ve()in the child immediately after forking (which is what you plan to do anyway).