Linux 何时检查 EINTR 并重复函数调用?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/4959524/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
When to check for EINTR and repeat the function call?
提问by stefangachter
I am programming a user application for a embedded Linux system, and I am using the common functions such as open, close, read, ioctl, etc. for the devices. Now, I read about EINTR, indicates that the function was interrupted by a signal, but I am not sure about the implications. In all the example programs I have, sometimes it is done, e.g. ioctl(), sometimes it is not done, e.g. read(). So, I am a little bit confused.
我正在为嵌入式 Linux 系统编写用户应用程序,我正在使用设备的常用功能,例如打开、关闭、读取、ioctl 等。现在,我读到有关 EINTR 的信息,表明该函数被信号中断,但我不确定其含义。在我拥有的所有示例程序中,有时完成,例如 ioctl(),有时未完成,例如 read()。所以,我有点困惑。
When do I preferably check for EINTR and repeat the function call?
我什么时候最好检查 EINTR 并重复函数调用?
采纳答案by Yann Droneaud
See sigaction : http://pubs.opengroup.org/onlinepubs/009695399/functions/sigaction.html
见 sigaction :http: //pubs.opengroup.org/onlinepubs/009695399/functions/sigaction.html
SA_RESTART
This flag affects the behavior of interruptible functions; that is, those
specified to fail with errno set to EINTR. If set, and a function specified
as interruptible is interrupted by this signal, the function shall restart
and shall not fail with EINTR unless otherwise specified. If the flag is not
set, interruptible functions interrupted by this signal shall fail with errno
set to EINTR.
By default, you have the SA_RESTART behavior, so you don't have to worry about EINTR, if you don't play with signals.
默认情况下,您具有 SA_RESTART 行为,因此如果您不使用信号,则不必担心 EINTR。
回答by Maxim Egorushkin
Is your application event driven? (Meaning its main loop include select()/epoll_wait()
call).
你的应用程序是事件驱动的吗?(意思是它的主循环包括select()/epoll_wait()
调用)。
In an event driven application you can block all signals and only unblock them for the duration of pselect()/epoll_pwait()
call. This way the rest of your code never have to deal with EINTR.
在事件驱动的应用程序中,您可以阻止所有信号,并且仅在pselect()/epoll_pwait()
通话期间取消阻止它们。这样,您的其余代码就不必处理 EINTR。
回答by lobosch
I had a similar problem when waiting for input from a named pipe with read().
在使用 read() 等待来自命名管道的输入时,我遇到了类似的问题。
I found an explanation and a useful macro for primitives in GNU libc documentation: TEMP_FAILURE_RETRY
我在GNU libc 文档中找到了对原语的解释和有用的宏:TEMP_FAILURE_RETRY
Example:
例子:
TEMP_FAILURE_RETRY (read_return = read((int)example_fifo, buffer, (size_t)n));
if (read_return==-1){
fprintf(stderr, "reader.c: read_fifo: read(): %s \n", strerror(errno));
fflush(stderr);
}
回答by R.. GitHub STOP HELPING ICE
I know this question is old but I think there's more to be said. To answer the specific question in the title: basically, never.
我知道这个问题很老,但我认为还有更多要说的。回答标题中的具体问题:基本上,从不。
Aside from select
and poll
, EINTR
can only happen if you've installed (either by mistake/not understanding how to use sigaction
, or because you wantto be able to interrupt blocking operations) interrupting signal handlers. Looping to retry when a function fails with EINTR
just undoes that. Doing so is an old anti-pattern from the 80s and early to mid 90s when lots of operating systems were buggy and reportedly generated EINTR
under non-conforming circumstances, but these bugs are long gone.
除了select
and之外poll
,EINTR
只有在您安装(错误地/不理解如何使用sigaction
,或者因为您希望能够中断阻塞操作)中断信号处理程序时才会发生。当一个函数失败时循环重试EINTR
只是撤消了那个。这样做是 80 年代和 90 年代早期到中期的一种旧的反模式,当时许多操作系统都有错误,据报道是EINTR
在不符合规定的情况下生成的,但这些错误早已不复存在。
It is possible that, even in an application where you want to be able to interrupt things with signals, there is some code whose successful completion is so important that you can't treat EINTR
as an error condition and return back to the caller without completing the operation. In such a circumstance, it might make sense to install a retry loop, but it's probably better to mask signals (at least the potentially-interrupting ones) during the operation and unmasks after it finishes.
有可能,即使在您希望能够用信号中断事物的应用程序中,也有一些代码的成功完成非常重要,以至于您不能将其EINTR
视为错误条件并在未完成的情况下返回给调用者手术。在这种情况下,安装重试循环可能是有意义的,但最好在操作期间屏蔽信号(至少是潜在中断的信号)并在完成后取消屏蔽。