如何知道Linux系统调用是否可以重启?

根据man 信号(7) ,如果在安装信号处理程序时使用SA_RESTART标志,那么某些系统调用可以被内核透明地重新启动:

如果以下接口之一的阻塞呼叫被信号处理程序中断, 则在信号处理程序返回后,如果使用SA_RESTART标志,呼叫将自动重新启动 ; 否则该调用将失败,出现错误EINTR:

然后它提到了一些可以(也不能)重新启动的系统调用,但是在两个地方都没有提到close() ,我怎么知道close()或者其他函数是否可以重新启动? POSIX指定它还是Linux特定的行为? 我在哪里可以find更多信息?

Solutions Collecting From Web of "如何知道Linux系统调用是否可以重启?"

根据POSIX.1-2008 , SA_RESTART标志适用于所有可中断的函数(所有被记录为EINTR失败的函数):

SA_RESTART

该标志影响可中断功能的行为; 也就是说,指定的errno设置为[EINTR]失败。 如果被设置,并且指定为可中断的功能被该信号中断,则除非另外指定,否则该功能将重新启动并且不会以[EINTR]失败。 如果重新启动使用超时的可中断功能,则重新启动后超时的持续时间将设置为未超出原始超时值的未指定值。 如果没有设置标志,由此信号中断的可中断功能将失败,并将errno设置为[EINTR]。

也就是说,没有重新启动的函数列表是特定于Linux的(可能算作一个错误)。

close是一个相当特殊的情况。 不仅在Linux上不能重启, 当在Linux上使用EINTR返回时,它实际上已经成功了,而另一个调用close将会在单线程进程中失败,并且在多线程进程中导致非常危险的文件描述符竞争。

从已发布的POSIX 2008开始,这种行为是允许的:

如果close()被一个被捕获的信号中断,它将返回-1,errno被设置为[EINTR],并且fildes的状态是未指定的。

这个问题是由奥斯汀集团提出的( 问题#529 ),并且决定修改规范,使用EINTR返回意味着文件描述符仍然是打开的; 这是违背当前的Linux行为。 如果在处理信号时文件描述符已经关闭,那么close函数现在需要返回EINPROGRESS而不是EINTR 。 这可以在Linux上的用户空间中修复,并且有一个开放的glibc错误报告,#14627 ,但在撰写本文时还没有收到任何回应。

这个问题也对POSIX线程取消有严重的影响,其副作用是用EINTR返回时的副作用来规定的。 奥斯汀集团的追踪器有一个相关的问题, 问题#614 。