简体   繁体   中英

Issue with dup2

I am trying a simple program where the STDOUT from Child process is directed to the Parent process. The program works if I don't fork multiple times and call the child_process and parent_process in a loop. However, when I put a for loop around the fork and child_process and parent_process , dup2 function returns -1 and hence the program fails. What am I doing wrong?

This code has a for loop around the child_process and parent_process and has issues with dup2

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
 
#define BUFSIZE 256
 
void child_process(int pipe_pair[2]){
 
    // closes the child's STDOUT descriptor and replaces it with
    // the write pipe linked to the parent's read pipe
    if (dup2(pipe_pair[1], STDOUT_FILENO) == -1){ 
      // if dup2 fails, perror writes to stderr so this reports
      // appropriately either way as the child and parent share stderr
      perror("dup2"); 
      // parent will know if the child failed since we return 1
      // (ideally return errno so that calling processes know the error code)
      exit(EXIT_FAILURE); 
    }   
 
    // duplicated by dup2 above, no longer needed
    close(pipe_pair[1]); 
    // close read end as we will never read from stdout
    close(pipe_pair[0]); 
 
    // printf writes to stdout by default
    // we could also use fprintf(stdout, ...)
    printf("Hello, parent!\n"); 
    // make sure the write buffer is flushed before we exit
    fflush(stdout); 
 
    // close to make sure read() returns 0 in the parent
    close(STDOUT_FILENO); 
 
    // child exits
    exit(EXIT_SUCCESS); 
}
 
void parent_process(int pipe_pair[2], pid_t cpid){
 
    // cstatus will store the return of the child process
    // buf will hold the child's writes to stdout --
    // {0} initializes the array elements to 0x00
    int cstatus; 
    char buf[BUFSIZE] = {0}; 
 
    close(pipe_pair[1]); // we won't write to stdout
 
    // read until closed, or error (0 or -1, respectively)
    for (int n = 0; (n = read(pipe_pair[0], buf, BUFSIZE)) > 0;){ 
      printf("Received %d bytes from child process: ", n); 
      // (needed otherwise write() may output before 
      // printf since stdio output to stdout is line buffered)
      fflush(stdout); 
      // writes just what we read so no need to reset buf
      write(STDOUT_FILENO, buf, n); 
      printf("\n");
      fflush(stdout);
    }   
 
    // close read pipe
    close(pipe_pair[0]); 
 
    // waits for child process with pid 'cpid' to
    // return and stores the exit code in cstatus
    waitpid(cpid, &cstatus, 0); 
 
    printf("Child exit status was: %d\n", cstatus);
 
    // terminate parent
    //exit(EXIT_SUCCESS); 
 
}
 
int main(int argc, char **argv){
 
  // cpid stores the process id of the child process
  // stdout_pipe array = pipe descriptor pair -- 
  // [0] is the read end, [1] is the write end
  pid_t cpid; 
  int stdout_pipe[2]; 
 
  // call that creates the two unidirectional pipe streams 
  // and stores the descriptors in the array
  if (pipe(stdout_pipe) == -1){ 
    perror("pipe");
    exit(EXIT_FAILURE);
  }
 
  // fork happens here, cpid will have the child's
  // process id or -1 if the call fails
  for (int i=0; i<3; i++) {
      cpid = fork(); 
      if (cpid == -1){
         perror("fork");
         exit(EXIT_FAILURE);
      }
 
      // child (fork returns 0 in the child and the child ID for the parent)
      if (cpid == 0) 
         child_process(stdout_pipe);
      // else when cpid is not 0 or -1 we're in the parent
      else 
         parent_process(stdout_pipe, cpid);
  }
  // we shouldn't get here, but return int from main for correctness
  return 0;
}

The problem is this block is outside the loop:

if (pipe(stdout_pipe) == -1){ 
  perror("pipe");
  exit(EXIT_FAILURE);
}

The first call to parent_process closes the pipe descriptors, and they are not reopened for the second iteration of the loop, so there is nothing to dup .

The simplest solution would be to move the pipe call in to the loop.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM