Search code examples
cprocesspipefork

Basic pipe does not terminate in c


I tried to run the following simple code:

int main(int argc, char* argv[]) {
    int fds[2];
    pipe(fds);
    int pid1, pid2;
    if ((pid1 = fork()) == 0){
        close(fds[0]); // close read end
        dup2(fds[1], 1); // connect write end
        char *argv1[2] = {"echo", "hi"};
        execvp(argv1[0], argv1);
    }
    if ((pid2 = fork()) == 0){
        close(fds[1]); // close write end
        dup2(fds[0], 0); // connect read end
        char *argv2[2] = {"wc", "-c"};
        execvp(argv2[0], argv2);
    } 
    int status;
    waitpid(pid1, &status, 0);
    printf("pid=%d terminated with status=%d\n", pid1, status);
    waitpid(pid2, &status, 0);
    printf("pid=%d terminated with status=%d\n", pid2, status);
    return 0;
}

I was expecting both the echo and wc to terminate, but the wc never does. The output I get for the above code is just something like below (and the main process gets suspended waiting for the wc to finish).

pid=2802 terminated with status=0

Any ideas why the second forked process doesn't finish?


I have checked, by trying to read from fds[0] after a short sleep at the main process, that the wc command has indeed read the hi message from the echo.


Solution

  • You need to close all of the write ends of the pipe. There are 4 copies of that file descriptor, and wc is not going to terminate until all of them are closed. The echo will close both of its copies when it terminates, but it's best practice to explicitly close the unused copy before you exec with:

    dup2(fds[1], STDOUT_FILENO);
    close(fds[1]);
    

    You need to also close that file descriptor in the parent before you call waitpid