cunixpipe

Program doesn't stop after reading from pipe


I am trying to understand pipes. I have this small program which uses a pipe to send a message from the parent process to its child. The child recieves all the 3 messages, but instead of exiting, after reading the last message it hangs. What am I doing wrong? Thanks.

PS: I noticed that if I would sleep for 2 seconds in the while loop from the parent, it would work.

#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>

int main(){

    int desc[2];
    pipe(desc);

    int pid = fork();

    if(pid == 0){
        while(1){
            sleep(1);
            char buffer[16];
            if(read(desc[0], buffer, 16) != 16){
                printf("Error or finished");
                exit(0);
            };
            printf("Child: message recieved - '%s'\n", buffer);
        }
        close(desc[1]);
    }
    if(pid > 0){
        int i=0;
        while(i <= 2){
            char buffer[100];
            i++; char x[10];
            strcpy(buffer, "Hello, child!");
            sprintf(x, " %d", i);
            strcat(buffer, x);
            if(write(desc[1], buffer, 16) != 16){
                printf("Error");
                exit(0);
            };
        }
        close(desc[0]);
    }
    return 0;
}

Solution

  • You forgot to close the unused ends of the pipes in both the parent and child processes. Actually your child possess reading and writing parts of the pipe, so it cannot detect the end-of-file as there exists a writer (itself!), so it is blocked in the read. Change your code to:

    if(pid == 0){
        close(desc[1]); // Child is not a writer, so close the write part immediately!
        while(1){
          ...
        }
    }
    if(pid > 0){
        close(desc[0]); // Parent is not a reader, so close the read part immediately!
        int i=0;
        while(i <= 2){
          ...
        }
    }
    

    Remember that on a pipe, end-of-file is "nothing more to read in the pipe" and "no more writer".