5

I'm experimenting some problems with this code:

#include <stdio.h>
#include <stdlib.h>

#define SIZE 30
#define Error_(x) { perror(x); exit(1); }
int main(int argc, char *argv[]) {

    char message[SIZE];
    int pid, status, ret, fd[2];

    ret = pipe(fd);
    if(ret == -1) Error_("Pipe creation");

    if((pid = fork()) == -1) Error_("Fork error");

    if(pid == 0){ //child process: reader (child wants to receive data from the parent)
        close(fd[1]); //reader closes unused ch.
        while( read(fd[0], message, SIZE) > 0 )
                printf("Message: %s", message);
        close(fd[0]);
    }
    else{//parent: writer (reads from STDIN, sends data to the child)
        close(fd[0]);
        puts("Tipe some text ('quit to exit')");
        do{
            fgets(message, SIZE, stdin);
            write(fd[1], message, SIZE);
        }while(strcmp(message, "quit\n") != 0);
        close(fd[1]);
        wait(&status);
    }
}

Code works fine but I can't explain why! There is no explicit sync between parent and child processes. If the child-process executes before parent, read must return 0 and the process ends, but for some reason it waits for the parent execution. How do you explain this? Maybe I'm missing something.

(Edited)

Fabio Carello
  • 1,062
  • 3
  • 12
  • 30

1 Answers1

5

Since you didn't use O_NONBLOCK in pipe2, read is blocking by default. Therefore it waits until data are written into the pipe.

P.P
  • 117,907
  • 20
  • 175
  • 238
md5
  • 23,373
  • 3
  • 44
  • 93
  • When `(fd[0], message, SIZE) > 0` in while condition is false? – Fabio Carello Feb 09 '13 at 12:53
  • It becomes false when the pipe is closed at the other end; if you didn't write anything yet, the reader assumes you may want to write something later. IOW the pipe acts as an implicit sync. – loreb Feb 09 '13 at 13:31
  • 2
    The pipe is not at all implicit. It is a very explicit synchronization mechanism. Probably the most common. Probably also the simplest. – William Pursell Feb 09 '13 at 13:33