tags:

views:

795

answers:

1

I'm creating various processes (3 to be precise) and making them do different things. So far so good. I'm trying to wait in the parent until all children are completed. I've played around with many options (such as the one listed below) but either the parent waits but I have to press enter to return to the shell (meaning that some child completes after the parent?) or the parent never returns to the shell. Any ideas? pointers to where to look for more help? Thanks

 #include <sys/types.h>
 #include <unistd.h>
 #include <stdio.h>
 #include <string.h>
 #include <errno.h>

 #define READ_END 0
 #define WRITE_END 1


int main (int argc, char **argv) 
{
pid_t pid;
int fd[2];
int fd2[2];

pipe(fd);
pipe(fd2);

for (int i=0; i<3; i++) {
    pid=fork();

    if (pid==0 && i==0) {

        //never uses fd2, so close both descriptors
        close(fd2[READ_END]);
        close(fd2[WRITE_END]);

        printf("i'm the child used for ls \n");
        close(fd[READ_END]); /*close read end since I don't need it */
        dup2(fd[WRITE_END], STDOUT_FILENO);
        close(fd[WRITE_END]);
        execlp("ls", "ls", "-hal", NULL);


        break; /*exit for loop to end child's code */
    }

    else if (pid==0 && i==1) {
        printf("i'm in the second child, which will be used to run grep\n");
        close(fd[WRITE_END]);
        dup2(fd[READ_END], STDIN_FILENO);
        close(fd[READ_END]);

        close(fd2[READ_END]);
        dup2(fd2[WRITE_END], STDOUT_FILENO);
        close(fd2[WRITE_END]);
        execlp("grep", "grep","p",NULL);
        break;
    }
    else if (pid==0 && i==2) {

        //never uses fd so close both descriptors
        close(fd[READ_END]);
        close(fd[WRITE_END]);

        printf("i'm in the original process which will be replaced with wc\n");

        close(fd2[WRITE_END]);
        dup2(fd2[READ_END], STDIN_FILENO);
        close(fd2[READ_END]);
        printf("going to exec wc\n");
        execlp("wc","wc","-w",NULL);
        break;
        }
        else {
        //do parenty things
        }
        }

        wait(NULL); 
        while (1){
                wait(NULL);
                if(errno== ECHILD) {
                    printf("all children ended\n"); 
                    break;
                }
                }




        close(fd[READ_END]);
        close(fd[WRITE_END]);
        close(fd2[READ_END]);
        close(fd2[WRITE_END]);






return 0;

}

+5  A: 

grep and wc never exit.

Why? They never receive an EOF on stdin.

Why? Because, even though ls has exited and closed the write end of pipe(fd), the main process still has the write end of pipe(fd) open, thus the read end of pipe(fd) is still waiting for more data. Similar thing goes for fd2: even if grep exited, wc wouldn't get an EOF on stdin.

Solution: close all the pipe fds in the main process before you wait.

ephemient
you're right! works flawlesly now! thanks for your help!
lordsandwich
you should click the check mark next to this answer if it answered your question
bdonlan