问题:
在一个close()系统调用失败并返回EINTR或EIO时,文件是否已经关闭是不确定的。 (http://pubs.opengroup.org/onlinepubs/9699919799/) 在多线程应用程序中,重新尝试关闭可能会关闭其他线程打开的无关文件。不重新尝试关闭可能导致无法使用的打开文件描述符增加。一种干净的解决方案可能涉及对新关闭的文件描述符进行fstat()调用和相当复杂的锁定机制。 此外,将所有的open/close/accept/... 调用与单个互斥锁串行化可能是一种选项。
这些解决方案没有考虑到库函数可能以不可控的方式自己打开和关闭文件,例如,一些实现std::thread::hardware_concurrency()的函数在/proc文件系统中打开文件。
如 [file.streams] C++ 标准部分所述的文件流不是一种选择。
在存在多个线程的情况下,是否有简单可靠的机制来关闭文件?
编辑:
常规文件: 虽然大多数时间不会积累无法使用的打开文件描述符,但两个条件可能会引发该问题: 1. 一些恶意软件以高频率发出信号 2. 在缓存刷新之前丢失连接的网络文件系统。
套接字:根据Stevens/Fenner/Rudoff的说法,如果在引用连接套接字的文件描述符上设置了SO_LINGER选项,并且在close()期间计时器到期之前FIN-ACK关闭序列完成,则close()将作为通用程序的一部分失败。 Linux没有显示这种行为,但FreeBSD确实如此,并且还将errno设置为EAGAIN。我理解,在这种情况下,是否失效文件描述符是不确定的。测试该行为的C++代码:http://www.longhaulmail.de/misc/close.txt 那里的测试代码输出对我来说看起来像是FreeBSD中的竞态条件,如果不是,为什么呢?
在调用close()期间,您可能需要考虑阻止信号。
close()
的返回值有多严重?,如何关闭文件?,系统调用被信号中断仍需完成等等(我找不到我想要找的那个)。基本上,你卡住了。你必须将文件描述符视为已关闭 - 除非它是由文件描述符创建函数返回的(在这种情况下,你可以安全地假设关闭是OK的),否则永远不要再使用它。 - Jonathan Leffler