有人可能会说一些关于异常的事情......但是在C中,有什么其他方法可以干净利落地清楚地完成以下操作并且不需要重复这么多代码?
if (Do1()) { printf("Failed 1"); return 1; }
if (Do2()) { Undo1(); printf("Failed 2"); return 2; }
if (Do3()) { Undo2(); Undo1(); printf("Failed 3"); return 3; }
if (Do4()) { Undo3(); Undo2(); Undo1(); printf("Failed 4"); return 4; }
if (Do5()) { Undo4(); Undo3(); Undo2(); Undo1(); printf("Failed 5"); return 5; }
Etc...
Run Code Online (Sandbox Code Playgroud)
这可能是使用gotos的一种情况.或者可能是多个内部功能......
注意:请在将此标记为重复之前阅读结尾.虽然它很相似,但我在答案中寻找的范围超出了之前的问题所要求的范围.
我倾向于认同的广泛实践往往close纯粹作为文件描述符的资源释放函数而不是具有有意义的失败案例的潜在IO操作.事实上,在解决问题529之前,POSIX在错误之后离开了文件描述符的状态(即它是否仍然被分配)未指定,使得无法以任何有意义的方式对错误进行可移植的响应.
然而,很多GNU软件都花了很大的力气来检查错误close,并且Linux手册页面的close调用失败了"这是一个常见的但仍然很严重的编程错误".NFS和配额被引用作为close可能产生错误但不提供细节的情况.
close在现实世界的系统中,哪些情况可能会失败?它们今天是否相关?我特别感兴趣的是知道是否有任何现代系统close因任何非NFS,非设备节点特定的原因而失败,以及对于NFS或与设备相关的故障,在什么条件下(例如配置)它们可能是看到.
在使用EINTR或EIO失败的close()系统调用之后,未指定文件是否已关闭.(http://pubs.opengroup.org/onlinepubs/9699919799/)在多线程应用程序中,重试关闭可能会关闭其他线程打开的不相关文件.不重试关闭可能导致无法打开的文件描述符堆积.一个干净的解决方案可能涉及在新近关闭的文件描述符上调用fstat()和一个非常复杂的锁定机制.此外,使用单个互斥锁序列化所有打开/关闭/接受/ ...调用可能是一种选择.
这些解决方案没有考虑库函数可能以不可控制的方式打开和关闭文件,例如,/ proc文件系统中的std :: thread :: hardware_concurrency()的一些实现打开文件.
文件流在[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可能被信号处理程序(有或没有SA_RESTART)中断的情况下调查/测试Linux上某些代码的行为.什么是最方便的设置,使close系统调用睡眠在一个可测量的时间窗口,在此期间,我可以尝试用信号命中过程?一些想法:
但是,由于这些设置有点痛苦,我想知道是否有更多现成的我可以使用它可以提供所需的行为.
想象以下代码作为线程运行:
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);
}
}
Run Code Online (Sandbox Code Playgroud)
fclose(3) 可能因各种原因而失败 - 是否有保证/何时关闭底层文件描述符或之后它仍然打开?