Search code examples
clinuxprocesspipefork

Child process read from pipe failed and seemed to be out of order


I have the following code with output:

#include <stdio.h>
#include <errno.h>
#include <unistd.h>
#include <string.h>
#include <wait.h>

#define PIPE_STDIN  0
#define PIPE_STDOUT 1

#define msg "hello world"

int main()
{
   int fd_pipe[2];

   int ret = fork();
   if (ret < 0)
   {
       printf("Failed to fork\n");
       return -1;
   }
   else if (ret == 0)
   {
       printf("Parent with PID %d\n", getpid());    fflush(stdout);
       //sleep(3);
       ret = write(fd_pipe[PIPE_STDOUT], msg, sizeof(msg));   fflush(stdout);
       printf("Parent wrote string %d\n", ret);     fflush(stdout);
       wait( NULL );
       printf("Parent done wait\n");    fflush(stdout);
   }
   else
   {
       char buf[80];
       printf("Child with PID %d whose parent PID %d\n", getpid(), ret);    fflush(stdout);
       ret = read(fd_pipe[PIPE_STDIN], buf, sizeof(msg));
       printf("Child read %s %d\n", buf, ret);  fflush(stdout);
   }
}

Output:

Child with PID 1130 whose parent PID 1131
Child read   -1
Parent with PID 1131
hello world Parent wrote string 12
Parent done wait

From the output, why would child failed to read from pipe (returned -1) and then later on message "hello world" was printed ? Please explain the execution order that gives the above log.


Solution

    1. You should call pipe before fork to init file descriptor.
    2. fork() == 0 means child process.

    The follow code could work:

    #include <stdio.h>
    #include <errno.h>
    #include <unistd.h>
    #include <string.h>
    #include <wait.h>
    
    #define PIPE_STDIN  0
    #define PIPE_STDOUT 1
    
    #define msg "hello world"
    
    int main()
    {
       int fd_pipe[2];
       int ret;
    
       if (pipe(fd_pipe) == -1) {
           perror("pipe");
           return -1;
       }
       ret = fork();
       if (ret < 0)
       {
           printf("Failed to fork\n");
           return -1;
       }
       else if (ret != 0)
       {
           printf("Parent with PID %d\n", getpid());    fflush(stdout);
           //sleep(3);
           ret = write(fd_pipe[PIPE_STDOUT], msg, sizeof(msg));   fflush(stdout);
           printf("Parent wrote string %d\n", ret);     fflush(stdout);
           wait( NULL );
           printf("Parent done wait\n");    fflush(stdout);
       }
       else
       {
           char buf[80];
           printf("Child with PID %d whose parent PID %d\n", getpid(), getppid());    fflush(stdout);
           ret = read(fd_pipe[PIPE_STDIN], buf, sizeof(msg));
           printf("Child read %s %d\n", buf, ret);  fflush(stdout);
       }
    }