无法关闭管道:错误的文件描述符

时间:2015-04-21 03:07:59

标签: c pipe fork

我有以下代码:

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));
}

我收到错误消息“ERROR,无法在主进程中关闭管道的写入结尾:错误的文件描述符”。我的印象是你应该在任何不使用该目的的过程中关闭管道的每一端。主流程不使用此处的管道。它的存在只是为了让两个孩子进行交流。此外,对close()的任何其他调用都没有其他错误。我不明白为什么父进程不能只关闭管道的写端。

1 个答案:

答案 0 :(得分:0)

我认为正在发生的事情是当子进程退出if语句时,它正在生成子进程并尝试隐藏已经关闭的管道:

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));
}

<强>解决方案

在if语句的末尾调用exit以防止子进程退出if语句并继续关闭管道。