无法关闭管道:错误的文件描述符
Can't close pipe: bad file descriptor
我有以下代码:
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, unable to close write end of pipe in main process: Bad file descriptor"。我的印象是你应该在任何不使用该端的进程中关闭管道的每一端。主进程在这里不使用管道。它的存在只是为了让两个children能够沟通。此外,对 close() 的任何其他调用都没有其他错误。我不明白为什么 parent 进程不能只关闭管道的写入端。
我认为发生的事情是当子进程退出 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 语句并继续关闭管道。
我有以下代码:
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, unable to close write end of pipe in main process: Bad file descriptor"。我的印象是你应该在任何不使用该端的进程中关闭管道的每一端。主进程在这里不使用管道。它的存在只是为了让两个children能够沟通。此外,对 close() 的任何其他调用都没有其他错误。我不明白为什么 parent 进程不能只关闭管道的写入端。
我认为发生的事情是当子进程退出 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 语句并继续关闭管道。