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

iab*_*der 12 c linux posix system-calls

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

如果对信号处理程序中断了对以下某个接口的阻塞调用,则在使用SA_RESTART标志后,如果信号处理程序返回,则调用将自动重新启动 ; 否则呼叫将失败并显示错误EINTR:

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

R..*_*R.. 11

close是一个相当特殊的案例.它不仅不能在Linux上重启; 当在Linux上close返回时EINTR,它实际上已经成功,并且进行另一次调用closeEBADF在单线程进程中失败并在多线程进程中导致极其危险的文件描述符争用.

截至发布的POSIX 2008,允许此行为:

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

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

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

  • 注意:此行为并非特定于linux.不能在linux,Solaris,Darwin(MacOS)和BSD上重试`close()`.HP-UX是唯一要求在EINTR上重试关闭的(?)系统.任何平台都无法改变其行为. (2认同)
  • 希望他们有非零的机会停止返回EINTR并开始返回EINPROGRESS或成功;POSIX中的修复程序都可以。我认为成功可能更可取,以免破坏认为“ EINTR”以外的其他值是致命错误的现有应用程序。 (2认同)

Max*_*nin 10

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

SA_RESTART

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

也就是说,未重新启动的函数列表是特定于Linux的(并且可能算作错误).

  • 注意措辞"除非另有说明".这就是这种情况,因此它比"bug"更具"实现细节"(这并不会让它变得不那么烦人,特别是因为文档经常与Linux一样,相当含糊). (4认同)