Home > OS >  Rust unix process
Rust unix process

Time:10-19

I am trying to use fork() for create child process and communicate it by pipes. I am using the nix library and os_pipe. When I try to execute the program, it is waiting and I can't see a message that I am sending in the child process to parent process. I try the drop function to close the pipe but not work. This is my code:

use nix::sys::wait::wait;
use nix::unistd::ForkResult::{Child, Parent};
use nix::unistd::{fork, getpid, getppid, pipe};
use std::io::prelude::*;

fn main() {
    let pid = fork();
    let (mut reader, mut writer) = os_pipe::pipe().unwrap();

    match pid.expect("Error during creating child") {
        Parent { child } => {
            println!("From parent, {}", getpid());
            wait().unwrap();
            let mut data = String::new();
            reader.read_to_string(&mut data).unwrap();
            println!("data: {}", data);
        }

        Child => {
            println!("from child, {}", getpid());
            writer.write_all("hello".as_bytes()).unwrap();
        }
    }
}

Thanks!!!

CodePudding user response:

First, you call fork() and then you create the pipes. As soon as fork() returns there are two processes (think as if fork() returns twice). That means that each process creates a separate pipe pair, unrelated to each other. Just swap those two lines so there is only one shared pipe (also you forgot an unsafe):

    let (mut reader, mut writer) = os_pipe::pipe().unwrap();
    let pid = unsafe { fork() };

Then, after the fork there are two copies of each end of the pipe, but since the parent is to do only reads and the child is to do only writes, you should close (drop) the unused ends:

    match pid.expect("Error during creating child") {
        Parent { child } => {
            drop(writer);
            //...
        }
        Child => {
            drop(reader);
            //...
        }

If you fail to close the writer in the parent, even when the child ends, the pipe will still be opened for writing and the parent will never reach the end of the pipe and read_to_string() will never finish. The drop(reader) is not actually needed here but it is good practice anyways: a failure to write to the pipe can be used by the child to detect that the parent has died.

  • Related