Question

I have two sets of code both trying to execute something like ls|grep pip One that works and one that does not.

The working code creates 2 child process and uses one child each to execlp the one command and the other simply tries to do this by creating one child. I.e executing ls in say the child and the grep in the parent. This does not seem to work. And I can't seem to get any error either.

Can someone tell me what the problem is? And why it exists?

Not Working:

void runpipe()
{
    pid_t childpid;
    int fd[2];
    pipe(fd);
    int saved_stdout;
    int saved_stdin;
    saved_stdout=dup(STDOUT_FILENO);
    saved_stdin=dup(STDIN_FILENO);
    if((childpid=fork())==0)
    {
            dup2(fd[WRITE_END],STDOUT_FILENO);
            close(fd[WRITE_END]);
            execlp("/bin/ls","ls command","-l",NULL);

            dup2(STDOUT_FILENO,fd[1]);
            _exit(0);
    }
    else if(childpid>0)
    {

            dup2(saved_stdout,STDOUT_FILENO);
            dup2(fd[READ_END],STDIN_FILENO);
            close(fd[READ_END]);
            execlp("/bin/grep","grep","pip",NULL);
            wait();
            _exit(0);

    }
    else
    {
            printf("ERROR!\n");
    }
}

Here are the codes:

Working:

    int runpipe(){
    pid_t pid;
    int fd[2];

    pipe(fd);
    int i;
    pid=fork();

    if (pid==0) {

            printf("i'm the child used for ls \n");
            dup2(fd[WRITE_END], STDOUT_FILENO);
            close(fd[READ_END]);
            execlp("ls", "ls", "-al", NULL);
            _exit(0);
    } else {
            pid=fork();

            if (pid==0) {
                    printf("i'm in the second child, which will be used to grep\n");
                    dup2(fd[READ_END], STDIN_FILENO);
                    close(fd[WRITE_END]);
                    execlp("grep", "grep","pip",NULL);
            }
            else wait();
    }
    return 0;
}

Was it helpful?

Solution

The parent needs to close the write side of the pipe before exec'ing grep. For some reason, your code with the two children closes that file descriptor, but does not in the code with only one child. You are leaving several descriptors open, but the write side on the pipe is the important one. The reader (the exec'd grep) will not finish until all copies of the write side of the pipe are closed. By failing to close it, the grep is the one holding it open so grep will never terminate, but just wait for more data.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top