如果close(2)遇到EIO错误,文件描述符是否仍然会被删除?

20

如果调用close(2)系统调用返回EIO错误,那么文件描述符是否会被删除?

如果是的话,难道不可能通过稍后重试来处理偶发的IO错误吗?如果不是,那该怎么防止文件描述符泄露呢?

1个回答

14

这是一个棘手的问题。然而,POSIX标准在 close() 的描述中涵盖了它:

如果 close() 被要捕获的信号中断,它将返回-1,并将errno设置为[EINTR],fildes的状态未指定。如果在close()期间从文件系统读取或写入时发生I/O错误,则可能会返回-1,并将errno设置为[EIO];如果返回此错误,则fildes的状态未指定。

因此,文件描述符的状态未由标准指定。

对于大多数实际用途来说,它是关闭的;即使它正式打开,你也几乎无法使用文件描述符。你可以尝试一个无害的操作(如 fcntl()F_GETFL),看看是否会收到EBADF回复,表示描述符已经被正式关闭。但是,如果它是打开的,并且EIO错误的原因是永久性的,则每次尝试对其执行任何操作(包括 fcntl()调用)时都可能会得到EIO。你可能永远不会获得另一个类似open的操作返回相同的描述符。如果死的文件描述符是打开但无法关闭的,则甚至不清楚使用dup2()指定“死”文件描述符作为目标是否能够成功。


9
如果您的程序是多线程的或使用信号处理程序,则使用 fcntl() 测试文件描述符可能并不直接,因为它可能已关闭,然后被重新用于其他用途。 - mark4o
如果使用像libuv这样的非stdio框架,这会是一个问题吗? - Breton
是的,这是使用open()close()及其相关函数构建的任何框架都会遇到的问题,因此除非libuv使用与open()close()不同的系统调用集(这相当不可能),否则它可能会遭受close()失败并使文件描述符处于不确定状态的问题。 - Jonathan Leffler
当收到EIO时,尝试再次关闭文件描述符怎么样? - Marco Pagliaricci
1
@MarcoPagliaricci:文件描述符的状态是未指定的。它可能已经关闭并且文件描述符被重用,因此重试可能会关闭其他东西。这很奇怪(而且相当不可能),但确实如此。如果close()失败,除了报告问题发生之外,对文件描述符执行任何操作都不安全。 - Jonathan Leffler
我同意,更好的做法是相信操作系统能够做正确的事情,例如不会存在内存泄漏等问题。 - Marco Pagliaricci

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