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

时间:2012-11-13 07:36:17

标签: c linux posix system-calls

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

  

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

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

2 个答案:

答案 0 :(得分:10)

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

  

SA_RESTART

     

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

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

答案 1 :(得分:10)

close是一个相当特殊的案例。它不仅不能在Linux上重启;当close在Linux上返回EINTR时,它实际上已经成功,并且在单线程进程中对close的另一次调用将失败并导致EBADF并导致极其危险的文件-descriptor在多线程进程中比赛。

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

  

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

此问题是由Austin Group(作为Issue #529)提出的,并且决定修改规范,以便使用EINTR返回意味着文件描述符仍处于打开状态;这与当前的Linux行为相反。如果在处理信号时文件描述符已经关闭,则close函数现在需要使用EINPROGRESS而不是EINTR返回。这可以在Linux上的用户空间中修复,并且有一个开放的glibc bug report, #14627,但在撰写本文时它没有收到任何响应。

此问题对POSIX线程取消也有严重影响,其副作用是根据EINTR返回时的副作用指定的。奥斯汀组跟踪器Issue #614上存在相关问题。