Home > Software engineering >  Problem on piping with shell command in C
Problem on piping with shell command in C

Time:10-13

Here i try to implement linux shell script with piping in c, and i try to do it by passing the output of 1st child process to the 2nd child, and then do "grep a", then it should return sth like this a 1 a 4 ,and it should end the program. But what i encounter is that, the output of 2nd child process is correct,output of "grep a" did come out, but the child process get stuck there and does not terminate itself, can anyone explain to me why this is happening? My parent process is keep waiting for the 2nd child process to end. But it just stuck there foreverfor some reason.

/* pipe4.c */
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include<sys/wait.h>
#include<stdio.h>
#include<stdlib.h>
#include <unistd.h>
int main(int agrc, char* agrv[])
{
  int pipefds[2];
    pid_t pid;
    pid_t pid2;
  int status;
  if(pipe(pipefds) == -1){
    perror("pipe");
    exit(EXIT_FAILURE);
  }
  pid = fork();
  if(pid == -1){
    perror("fork");
    exit(EXIT_FAILURE);
  }
  if(pid == 0){
  //replace stdout with the write end of the pipe
    dup2(pipefds[1],STDOUT_FILENO);  
  //close read to pipe, in child    
    close(pipefds[0]);               
    execlp("cat","cat","try.txt",NULL);
  }else{
        waitpid(pid, &status, 0);
        printf("first child done\n");
        pid2 = fork();
        if(pid2 == 0){
            printf("second child start\n");
            dup2(pipefds[0],STDIN_FILENO);  
            close(pipefds[1]);               
            execlp("grep","grep","a",NULL);
        }
        else{
            waitpid(pid2, &status, 0);
            printf("second child end\n");
            close(pipefds[0]);
            close(pipefds[1]);
            exit(EXIT_SUCCESS);
            printf("end\n");
        }
    }   
}

CodePudding user response:

The grep is waiting for all processes to close the write side of the pipe. The parent is waiting for grep to finish before it closes the write side of the pipe. That's a deadlock. The parent needs to close the pipe ends before it calls waitpid

Note that the boiler plate for dup2 is:

dup2(pipefds[1],STDOUT_FILENO);     
close(pipefds[0]); 
close(pipefds[1]);

as you need to close both ends of the pipe. I believe this is not causing an issue in your current setup, but it's not worth thinking too hard about. Just close both ends of the pipe.

  • Related