如果fclose()失败,文件描述符还会保持打开状态吗?

9

想象以下代码作为一个线程运行:

void *thread_worker(void *q) {
 for (;;) {
  int fd = some_queue_get(q);
  FILE *writer = fdopen(fd, "w");
  if (!writer) { perror("fdopen"; close(fd); continue; }
  // do something with writer

  if (fclose(writer) == EOF) {
   perror("fclose writer");
   // should fd be closed here?
   close(fd);
  }
}

fclose(3) 可能因各种原因失败,有保证底层文件描述符关闭或仍然打开的方式/时间吗?

  • 如果fd在刷新失败时未被fclose关闭,则会泄漏fds而无需额外的关闭。
  • 如果fd被fclose关闭,则另一个线程新打开的文件描述符可能会被额外关闭。

2
从文档中得知:如果 fclose 失败,任何进一步的访问(包括对 fclose 的另一个调用)都会导致未定义的行为。 - Jabberwocky
1
@Jabberwocky 我不想访问流,而是文件描述符。 - thejonny
1
根据您的函数名称 - thread_workerclose(fd)危险的。如果 fclose() 已经关闭了它的文件描述符,但无论如何失败了,另一个线程可能会重复使用该值,而您将从另一个线程中关闭它。 - Andrew Henle
1
@AndrewHenle 正如thejonny在最后一句所写的那样... - Thomas
@thejonny:如果你使用的操作系统不能保证close释放FD,那么你只能接受可能会出现泄漏文件描述符的情况。你绝不能在失败后重试fclose,也不能尝试关闭底层FD。幸运的是,你不太可能使用这样的操作系统。例如,“Linux内核总是在关闭操作中尽早释放文件描述符,使其可以重新使用;可能返回错误的步骤(例如将数据刷新到文件系统或设备)仅发生在关闭操作的后期。”(来自man close) - rici
显示剩余4条评论
2个回答

2

man fclose 在我的系统上也没有提供答案,但是man 3p fclose揭示了 POSIX程序员手册的官方版本,该版本在这个问题上更加全面:

fclose()函数应执行与指向流的流相关联的文件描述符上的close()相当的操作。


3
但是close()函数可能失败,除了记录日志外,你无能为力。特别地,你不能安全地重试close()函数。 - Andrew Henle
这也符合当前的glibc行为,但不符合在谷歌搜索中找到的第一个glibc源代码(一个古老版本)的行为 :) - thejonny

0

答案是不行,C标准对此存在歧义(重点在于“我”):

7.21.5.1 The fclose function

Synopsis

#include <stdio.h>
int fclose(FILE *stream);
 

Description
A successful call to the fclose function causes the stream pointed to by stream to be flushed and the associated file to be closed. Any unwritten buffered data for the stream are delivered to the host environment to be written to the file; any unread buffered data are discarded. Whether or not the call succeeds, the stream is disassociated from the file and any buffer set by the setbuf or setvbuf function is disassociated from the stream (and deallocated if it was automatically allocated).

Returns
The fclose function returns zero if the stream was successfully closed, or EOF if any errors were detected.


C标准是无关紧要的,因为文件描述符不是标准C概念。您需要查看一些POSIX / Unix规范/实现,以了解fclose对文件描述符的影响。 - Gilles 'SO- stop being evil'
@Gilles'SO-stopbeingevil':如果通过丢弃FILE结构而保持相关联的文件描述符打开来实现流与文件分离,那将是一种错误的做法。然而,还有一个更普遍的问题:即使在生产代码中,我从未见过任何人处理close()因某种原因而失败的情况。如果它被信号中断,close()会失败,errno被设置为EINTR,并且文件描述符仍然打开。 - chqrlie

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接