SA_RESTART
根据man 信号(7),如果在安装信号处理程序时使用了标志,则内核可以透明地重启某些系统调用:
如果对信号处理程序中断了对以下某个接口的阻塞调用,则在使用SA_RESTART标志后,如果信号处理程序返回,则调用将自动重新启动 ; 否则呼叫将失败并显示错误EINTR:
然后它提到了一些可以(并且不能)重新启动的系统调用,但是close()
在任何一个地方都没有提到,我怎么知道是否close()
可以重启或其他任何功能?是POSIX
指定它还是特定于Linux的行为?我在哪里可以找到更多信息?
在使用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( fd )
可以被信号中断.在这种情况下,通常-1
会返回并errno
设置EINTR
.
问题是做什么是正确的?说,我仍然希望fd
关闭它.
我能想到的是:
while( close( fd ) == -1 )
if( errno != EINTR ) {
ReportError();
break;
}
Run Code Online (Sandbox Code Playgroud)
任何人都可以建议更好/更优雅/标准的方式来处理这种情况吗?
更新:正如mux所注意到的,RESTART
在安装信号处理程序时可以使用SA_ 标志.有人可以告诉我哪些功能可以保证在所有POSIX
系统上都可以重启(不仅仅是Linux
)?