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

标签 c linux posix system-calls

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

If a blocked call to one of the following interfaces is interrupted by a signal handler, then the call will be automatically restarted after the signal handler returns if the SA_RESTART flag was used; otherwise the call will fail with the error EINTR:

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

最佳答案

close 是一个相当特殊的情况。它不仅在 Linux 上不可重启;当 close 在 Linux 上返回 EINTR 时,它实际上已经成功了,再次调用 close 将失败并返回 EBADF 在单线程进程中,并在多线程进程中导致极其危险的文件描述符竞争。

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

If close() is interrupted by a signal that is to be caught, it shall return -1 with errno set to [EINTR] and the state of fildes is unspecified.

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

这个问题对 POSIX 线程取消也有严重的影响,其副作用是根据返回 EINTR 的副作用指定的。 Austin Group 跟踪器上有一个相关问题,Issue #614 .

关于c - 如何知道 Linux 系统调用是否可重启?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13357019/

相关文章:

c - 只读来自 FILE 对象的缓冲日期

c - 奇怪的值被初始化为数组

无法让我的列表用逗号正确打印出来

c - 使用 ptrace 跟踪子进程中的所有 execve() 调用

linux - 如何组合两个不同的linux命令?

posix - 我可以假设没有人是65534吗?

c++ - POSIX 套接字和 BSD 套接字有什么区别?

在C中的特定地址构造数组

linux - 在 Linux 上将 .fla 文件转换为 .swf

c++ - 重载新运算符以将对象存储在 mmap 文件中