Monu Didi
Monu Didi

Reputation: 17

Reading writes of child process from parent process

In the following code, I am forking 5 times to create 5 child process each of which receives
a string from parent process and the child process writes child-i back to the parent process
where i is the loop counter in the for loop of child process. When I run this program I
only see child-0 and then the program hangs.

int main(int argc, char *argv[])
{

    int num_processes = 5;
    int pipefd[2 * num_processes][2];
    pid_t cpid;
    char buf;

    if (argc != 2)
    {
        fprintf(stderr, "Usage: %s <string>\n", argv[0]);
        exit(EXIT_FAILURE);
    }
    for (int i = 0; i < 2 * num_processes; i++)
    {
        if (pipe(pipefd[i]) == -1)
        {
            perror("pipe");
            exit(EXIT_FAILURE);
        }
    }

    for (int i = 0; i < num_processes; i++)
    {
        cpid = fork();

        if (cpid == -1)
        {
            perror("fork");
            exit(EXIT_FAILURE);
        }

        if (cpid == 0)
        {                        /* Child reads from pipe */
            close(pipefd[i][1]); /* Close unused write end */

            while (read(pipefd[i][0], &buf, 1) > 0)
            {
            }
            char buf[12];
            snprintf(buf, 12, "child-%d", i);
            write(pipefd[num_processes + i][1], buf, strlen(buf));
            write(STDOUT_FILENO, "\n", 1);
            close(pipefd[i][0]);
            close(pipefd[num_processes + i][0]);
            break;
        }
        else
        { /* Parent writes argv[1] to pipe */
            /* Close unused read end */
            write(pipefd[i][1], argv[1], strlen(argv[1]));
            close(pipefd[i][1]); /* Reader will see EOF */
            wait(NULL);          /* Wait for child */
            char buf;
            while (read(pipefd[num_processes + i][0], &buf, 1) > 0)
            {
                write(STDOUT_FILENO, &buf, 1);
            }
            close(pipefd[num_processes + i][0]);
        }
    }
    _exit(EXIT_SUCCESS);
}

Upvotes: 0

Views: 950

Answers (1)

John Bollinger
John Bollinger

Reputation: 181074

When I run this program I only see child-0 and then the program hangs.

Yes, because the parent waits indefinitely to read more data from pipefd[num_processes + i][0]. Consider this:

            while (read(pipefd[num_processes + i][0], &buf, 1) > 0)

Judging by other parts of your code, you seem to appreciate that a process will not see EOF on reading from a pipe until the write end is closed, but perhaps you don't recognize that all handles on the write end need to be closed before the underlying open file description is closed. Or perhaps you simply aren't taking into account that the parent process has a copy of each end of each pipe it creates. It will never see EOF on pipefd[num_processes + i][0] as long as it has pipefd[num_processes + i][1] open, no matter what the child does.

As a best practice for working with pipes, each process involved should close each pipe end as soon as it no longer has need to hold it open. Especially the write ends, as failing to close those is prone to getting you into deeper trouble, but leaving the read ends open can produce a resource leak, and that can bite you, too.

Upvotes: 1

Related Questions