Home > Enterprise >  Using pipes: read in child and write in parent or vice versa
Using pipes: read in child and write in parent or vice versa

Time:03-19

In this simple program, the child process is reading from the pipe and the parent process writes to it.

int main()
{
    int fd[2];
    pipe(fd);

    pid_t pid = fork();
    switch (pid)
    {
        case 0:
        {
            close(fd[1]);
            char buf[16];
            ssize_t ret = read(fd[0], buf, sizeof buf);

            printf("[%d] read() returned %ld bytes: '%s'\n", getpid(), ret, buf);
            close(fd[0]);
        }
        break;

        default:
        {
            close(fd[0]);
            ssize_t ret = write(fd[1], "text", 5);

            printf("[%d] write() returned %ld bytes\n", getpid(), ret);
            close(fd[1]);
            while(wait(NULL) > 0);
            break;
        }
    }
}

Everything works as expected and the output looks something like this:

[1738] write() returned 5 bytes
[1739] read() returned 5 bytes: 'text'

Now, the problem starts when I reverse the roles here -- let the parent read from the pipe and let the child write to it:

int main()
{
    int fd[2];
    pipe(fd);

    pid_t pid = fork();
    switch(pid)
    {
        case 0:
        {
            close(fd[0]);
            ssize_t ret = write(fd[1], "text", 5);
            printf("[%d] write() returned %ld bytes\n", getpid(), ret);
            close(fd[1]);
        }
        break;
        default:
        {
            close(fd[1]);
            char buf[16];
            ssize_t ret = read(fd[0], buf, sizeof buf);

            printf("[%d] read() returned %ld bytes: '%s'\n", getpid(), ret, buf);

            close(fd[0]);
            while (wait(NULL))
                ;
        }
        break;
    }

}

and the output is

[1752] read() returned 5 bytes: 'text'
[1753] write() returned 5 bytes
^C

This looks fine except I have to send a SIGINT to terminate the process (I guess the parent one). Why do I get this behavior?

CodePudding user response:

wait() returns -1 in the event of an error, including when the calling process has no (more) child processes to wait for. It returns the PID of the child that was collected on success. Valid PIDs are all greater than 0, so wait() never returns 0. As a result, your ...

            while(wait(NULL))
                ;

... never terminates.

The ...

            while(wait(NULL) > 0);

... of the first code makes more sense, though it's a bit obscure. It makes one more call to wait() than is needed. Since you know how many children to wait for (one), it would be clearer to get the status code that wait() can provide, and interrogate it to determine whether to wait() again.

  • Related