1
votes

I have the following code:

int fds[2];
if (pipe(fds) < 0) {
    fprintf(stderr, "ERROR, unable to open pipe: %s\n", strerror(errno));
}
if (fcntl(fds[0], F_SETFL, O_NONBLOCK) < 0) {
    fprintf(stderr, "ERROR, unable make read end non-blocking: %s\n", strerror(errno));
}

pid_t pid1 = fork();
if (pid1 == 0) {
    if (close(fds[0]) < 0) {
        fprintf(stderr, "ERROR, unable to close read end of pipe: %s\n", strerror(errno));
    }

    // go on to write something
}

pid_t pid2 = fork();
if (pid2 == 0) {
    if (close(fds[1]) < 0) {
        fprintf(stderr, "ERROR, unable to close write end of pipe: %s\n", strerror(errno));
    }

    // go on to read something
}

if (close(fds[1]) < 0) {
    fprintf(stderr, "ERROR, unable to close write end of pipe in main process: %s\n", strerror(errno));
}
if (close(fds[0]) < 0) {
    fprintf(stderr, "ERROR, unable to close read end of pipe in main process: %s\n", strerror(errno));
}

I get the error message "ERROR, unable to close write end of pipe in main process: Bad file descriptor". I was under the impression that you should close each end of a pipe in any process which doesn't use that end. The main process does not use the pipe here. It exists only to allow the two children to communicate. In addition, there are no other errors on any of the other calls to close(). I don't understand why the parent process can't close only the write end of the pipe.

1
How do you know it's the main process that's failing to close it? - user253751

1 Answers

0
votes

I think what is happening is when the child process exits the if statement, it is spawning a child process and trying to cloes a pipe that is already closed:

pid_t pid1 = fork();
if (pid1 == 0) {
    // child 1 comes here
    if (close(fds[0]) < 0) {
        fprintf(stderr, "ERROR, unable to close read end of pipe: %s\n", strerror(errno));
    }

    // go on to write something

    // << you were supposed to call exit here. Child 1 passes through.
}

pid_t pid2 = fork();
if (pid2 == 0) {
    // child 2 comes here first, but after that,
    // child 1 will respawn a new child (child 3). Child 3
    // closes a different pipe so no crash here.

    if (close(fds[1]) < 0) {
        fprintf(stderr, "ERROR, unable to close write end of pipe: %s\n", strerror(errno));
    }

    // go on to read something

    // Big problem: Child 2 and Child 3 will pass through here.
}

// The main thread, as well as children 1, 2 and 3 are all here now.
// if any 2 threads try to close this pipe, you will get an error:

if (close(fds[1]) < 0) {
    fprintf(stderr, "ERROR, unable to close write end of pipe in main process: %s\n", strerror(errno));
}

Solution

Call exit at the end of the if statements to prevent the children from exiting the if statements and continuing on to close the pipe.