对fclose进行适当的错误处理是不可能的(根据联机帮助页)?

前端之家收集整理的这篇文章主要介绍了对fclose进行适当的错误处理是不可能的(根据联机帮助页)?前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
所以我正在研究fclose manpage,而我的结论是,如果fclose被某些信号中断,根据联机帮助页有没有办法恢复……?我错过了一些观点吗?

通常,使用无缓冲的POSIX功能(打开,关闭,写入等),总有一种方法可以通过重新启动呼叫来从信号中断(EINTR)中恢复;相反,缓冲调用的文档说明在fclose尝试失败后,另一次尝试有未定义的行为…没有关于如何恢复的提示.如果信号中断fclose,我只是“不幸”吗?数据可能会丢失,我无法确定文件描述符是否实际关闭.我知道缓冲区已被释放,但文件描述符呢?
考虑大量使用fd的批量应用程序,如果没有正确释放fd,会遇到问题 – >我认为必须有一个CLEAN解决方案来解决这个问题.

所以我们假设我正在编写一个库并且不允许使用sigaction和SA_RESTART并且发送了大量信号,如果fclose被中断,我该如何恢复?
fclose与EINTR失败后,在循环(而不是fclose)中调用close是不是一个好主意? fclose的文档根本没有提到文件描述符的状态;虽然UNDEFINED不是很有帮助…如果fd关闭并且我再次打电话给关闭,可能会发生奇怪的难以调试的副作用,所以我宁愿忽略这种情况,因为做了错误的事情……然后,那里没有无限数量文件描述符可用,资源泄漏是某种错误(至少对我而言).

当然我可以检查fclose的一个具体实现,但我不相信有人设计stdio并且没有考虑这个问题?它只是文档是坏的还是这个函数的设计?

这个角落案件真的让我烦恼:(

解决方法

EINTR和关闭()

事实上,close()也存在问题,而不仅仅是fclose().

POSIX声明close()返回EINTR,这通常意味着应用程序可能会重试该呼叫.但是Linux中的事情比较复杂.见LWN上的this articlethis post.

[...] the POSIX EINTR semantics are not really possible on Linux. The file descriptor passed to close() is de-allocated early in the processing of the system call and the same descriptor could already have been handed out to another thread by the time close() returns.

This blog postthis answer解释了为什么用EINTR重试close()失败并不是一个好主意.所以在Linux中,如果close()因EINTR(或EINPROGRESS)失败,你就无能为力.

另请注意,close()在Linux中是异步的.例如,有时umount可能会在关闭文件系统上的最后一个打开的描述符后立即返回EBUSY,因为它尚未在内核中释放.请参阅此处有趣的讨论:page 1,page 2.

EINTR和fclose()

POSIX指出fclose()

After the call to fclose(),any use of stream results in undefined behavior.

Whether or not the call succeeds,the stream shall be disassociated from the file and any buffer set by the setbuf() or setvbuf() function shall be disassociated from the stream. If the associated buffer was automatically allocated,it shall be deallocated.

我相信这意味着即使close()失败,fclose()也应该释放所有资源并且不会产生泄漏.至少对于glibcuclibc实现来说这是真的.

可靠的错误处理

>在fclose()之前调用fflush().

由于在调用fflush()或close()时无法确定fclose()是否失败,因此必须在fclose()之前显式调用fflush()以确保成功将用户空间缓冲区发送到内核.
>不要在EINTR之后重试.

如果fclose()使用EINTR失败,则无法重试close(),也无法重试fclose().
>如果需要,请调用fsync().

>如果您关心数据完整性,则应在调用fclose()1之前调用fsync()或fdatasync().
>如果不这样做,只需忽略fclose()中的EINTR即可.

笔记

>如果fflush()和fsync()成功并且fclose()因EINTR而失败,则不会丢失任何数据且不会发生泄漏.
>您还应确保在来自另一个线程2的fflush()和fclose()调用之间不使用FILE对象.

[1]参见“Everything You Always Wanted to Know About Fsync()”文章,该文章解释了为什么fsync()也可能是异步操作.

[2]你可以在调用fflush()和fclose()之前调用flockfile().它应该正确使用fclose().

猜你在找的C&C++相关文章