如果 posix 关闭调用失败怎么办?
What to do if a posix close call fails?
在我的系统(Ubuntu Linux、glibc)上,close
调用的手册页指定了它可以 return 的几个错误 return 值。它还说
Not checking the return value of close() is a common but nevertheless serious programming error.
同时
Note that the return value should only be used for diagnostics. In particular close() should not be retried after an EINTR since this may cause a reused descriptor from another thread to be closed.
所以我不能忽略 return 值,也不能重试调用。
那么,close()
调用失败怎么处理?
如果在我向文件写入内容时发生错误,我可能应该尝试将信息写入其他地方以避免数据丢失。
如果我只是在读取文件,我可以只记录失败并假装什么都没发生继续程序吗?是否有任何注意事项、文件描述符泄漏或其他问题?
首先:EINTR
的意思就是:系统调用被中断,如果这种情况发生在 close()
调用上,您将无能为力。
除了可能跟踪事实之外,如果 fd 属于一个文件,则该文件可能已损坏,对于 close()
上的错误,您根本无能为力 - 取决于return 值。据我所知,唯一可以重试关闭的情况是 EBUSY
,但我还没有看到。
所以:
- 不检查
close()
的结果可能意味着您错过了文件损坏,尤其是截断。
- 根据错误的不同,大多数时候您无能为力 - 失败
close()
只是意味着在您的应用程序范围之外出现了严重错误。
在实践中,close
永远不应该在出错时重试,并且你传递给 close
的 fd 在 close
returns 之后总是无效(关闭),不管是否发生错误。在某些情况下,错误可能表明数据已丢失(某些 NFS 设置)或设备的异常硬件条件(例如磁带无法倒带),因此您可能需要谨慎以避免数据丢失,但您永远不应尝试再次关闭fd。
理论上,POSIX过去不清楚当close
因EINTR
失败时fd是否保持打开状态,系统不同意。由于了解状态很重要(否则你会遇到 fd 泄漏或双关闭错误,这在多线程程序中是极其危险的),解决方案 Austin Group issue #529 specified the behavior strictly for future versions of POSIX, that EINTR
means the fd remains open. This is the right behavior consistent with the definition of EINTR
elsewhere, but Linux refuses to accept it. (FWIW there's an easy workaround for this that's possible at the libc syscall wrapper level; see glibc PR #14627。幸运的是,它在实践中从未出现过。
您可能会发现一些相关的问题:
- What are the reasons to check for error on close()?
- Trying to make close sleep on Linux
在我的系统(Ubuntu Linux、glibc)上,close
调用的手册页指定了它可以 return 的几个错误 return 值。它还说
Not checking the return value of close() is a common but nevertheless serious programming error.
同时
Note that the return value should only be used for diagnostics. In particular close() should not be retried after an EINTR since this may cause a reused descriptor from another thread to be closed.
所以我不能忽略 return 值,也不能重试调用。
那么,close()
调用失败怎么处理?
如果在我向文件写入内容时发生错误,我可能应该尝试将信息写入其他地方以避免数据丢失。
如果我只是在读取文件,我可以只记录失败并假装什么都没发生继续程序吗?是否有任何注意事项、文件描述符泄漏或其他问题?
首先:EINTR
的意思就是:系统调用被中断,如果这种情况发生在 close()
调用上,您将无能为力。
除了可能跟踪事实之外,如果 fd 属于一个文件,则该文件可能已损坏,对于 close()
上的错误,您根本无能为力 - 取决于return 值。据我所知,唯一可以重试关闭的情况是 EBUSY
,但我还没有看到。
所以:
- 不检查
close()
的结果可能意味着您错过了文件损坏,尤其是截断。 - 根据错误的不同,大多数时候您无能为力 - 失败
close()
只是意味着在您的应用程序范围之外出现了严重错误。
在实践中,close
永远不应该在出错时重试,并且你传递给 close
的 fd 在 close
returns 之后总是无效(关闭),不管是否发生错误。在某些情况下,错误可能表明数据已丢失(某些 NFS 设置)或设备的异常硬件条件(例如磁带无法倒带),因此您可能需要谨慎以避免数据丢失,但您永远不应尝试再次关闭fd。
理论上,POSIX过去不清楚当close
因EINTR
失败时fd是否保持打开状态,系统不同意。由于了解状态很重要(否则你会遇到 fd 泄漏或双关闭错误,这在多线程程序中是极其危险的),解决方案 Austin Group issue #529 specified the behavior strictly for future versions of POSIX, that EINTR
means the fd remains open. This is the right behavior consistent with the definition of EINTR
elsewhere, but Linux refuses to accept it. (FWIW there's an easy workaround for this that's possible at the libc syscall wrapper level; see glibc PR #14627。幸运的是,它在实践中从未出现过。
您可能会发现一些相关的问题:
- What are the reasons to check for error on close()?
- Trying to make close sleep on Linux