Search code examples
cpipeforkfile-descriptor

Pipe() and fork()


The goal of my program is to create two pipes and two processes that communicate each other reading and writing to the pipes.

  1. process p1 reads from pipe c1 and writes to the pipe c2
  2. process p2 reads from pipe c2 and writes to the pipe c1

Until the read number from the pipe is less than BIG_INT_STOP the two processes continue to increment the number in the pipes. As soon as this condition is true, first process that reads it, close the pipes, exit and prints the number. The problem is: when the process p2 ends before p1 it works and when the process p1 ends before p2 it goes in loop. Can you explain me why?

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/sysinfo.h>
#include <sys/wait.h>
#include <errno.h>
#include <time.h>
#include <string.h>
#define BIG_INT_STOP 40
#define TEST_ERROR    if (errno) {fprintf(stderr, \
                  "%s:%d: PID=%5d: Error %d (%s)\n", \
                  __FILE__,         \
                  __LINE__,         \
                  getpid(),         \
                  errno,            \
                  strerror(errno));}

int main(){
  int c1[2], c2[2], p1, p2, z;
  long a = 0, c;
  pipe(c1);
  pipe(c2);
  write(c1[1], &a, sizeof(a));
  write(c2[1], &a, sizeof(a));
  p1 = fork();
  p2 = fork();
  switch(p1){
    case -1:
      TEST_ERROR;
      exit(EXIT_FAILURE);
    case 0:
      read(c1[0], &c, sizeof(c));
      while(c != BIG_INT_STOP){
        ++c;
        write(c2[1], &c, sizeof(c));
        read(c1[0], &c, sizeof(c));
      }
      close(c1[0]);
      close(c1[1]);
      close(c2[0]);
      close(c2[1]);
      printf("p1: %ld\n", c);
      exit(0);
  }
  switch(p2){
    case -1:
      TEST_ERROR;
      exit(EXIT_FAILURE);
    case 0:
      read(c2[0], &c, sizeof(c));
      while(c != BIG_INT_STOP){
        ++c;
        write(c1[1], &c, sizeof(c));
        read(c2[0], &c, sizeof(c));
      }
      close(c1[0]);
      close(c1[1]);
      close(c2[0]);
      close(c2[1]);
      printf("p2: %ld\n", c);
      exit(0);
  }
  while(wait(&z) != -1);
}

Solution

  • Your program is a bit strange. The main problem seems to be that the second fork is executed in both main program and in the first child. In fact you are running four processes: main, two sons of main and the son of the first son. This is probably not what you want. You probably wanted to put the first switch immediately after the first fork and to execute the second fork only in the main program.

    And, of course, you are not checking result values of read and write for unexpected situations.