如何处理EINTR(中断的系统调用)

Mau*_*aus 5 c c++ linux

我的用户空间应用程序有时会在收到EINTR信号后以某种方式阻塞.

我用strace录制的内容:

time(NULL)                              = 1257343042
time(NULL)                              = 1257343042
rt_sigreturn(0xbff07be4)                = -1 EINTR (Interrupted system call)
--- SIGALRM (Alarm clock) @ 0 (0) ---
time(NULL)                              = 1257343042
futex(0xb7cea80c, 0x80 /* FUTEX_??? */, 2) = ? ERESTARTSYS (To be restarted)
--- SIGUSR1 (User defined signal 1) @ 0 (0) ---
sigreturn()                             = ? (mask now [ALRM])
futex(0xb7cea80c, 0x80 /* FUTEX_??? */, 2) = ? ERESTARTSYS (To be restarted)
--- SIGWINCH (Window changed) @ 0 (0) ---
futex(0xb7cea80c, 0x80 /* FUTEX_??? */, 2) = ? ERESTARTSYS (To be restarted)
--- SIGTERM (Terminated) @ 0 (0) ---
time(NULL)                              = 1257343443
time(NULL)                              = 1257343443
futex(0xb7cea80c, 0x80 /* FUTEX_??? */, 2) = ? ERESTARTSYS (To be restarted)
--- SIGWINCH (Window changed) @ 0 (0) ---
futex(0xb7cea80c, 0x80 /* FUTEX_??? */, 2
Run Code Online (Sandbox Code Playgroud)

我可以捕获EINTR信号吗?如何重复写入,读取或选择等有关的呼叫?即使我使用第三方库处理系统调用,如何确定此EINTR发生的位置?

为什么我的应用程序在收到EINTR后被完全阻止(请参阅strace转储:我发送了一个通常应该处理的SIGUSR1)?为什么futex()将ERESTARTSYS返回给用户空间?

谢谢

Ste*_*sop 17

调用write(或其他阻塞操作)的代码必须知道EINTR.如果在阻塞操作期间发生信号,则操作将(a)返回部分完成,或(b)返回失败,什么都不做,并将errno设置为EINTR.

因此,对于在中断后重试的全失败写操作,您可以执行以下操作:

while(size > 0) {
    int written = write(filedes, buf, size);
    if (written == -1) {
        if (errno == EINTR) continue;
        return -1;
    }
    buf += written;
    size -= written;
}
return 0; // success
Run Code Online (Sandbox Code Playgroud)

或者对于表现更好的东西,重试EINTR,尽可能多地写入,并报告失败时写入多少(因此调用者可以决定是否以及如何继续部分写入因为信号中断之外的原因而失败):

int total = 0;
while(size > 0) {
    int written = write(filedes, buf, size);
    if (written == -1) {
        if (errno == EINTR) continue;
        return (total == 0) ? -1 : total;
    }
    buf += written;
    total += written;
    size -= written;
}
return total; // bytes written
Run Code Online (Sandbox Code Playgroud)

GNU有一个非标准的TEMP_FAILURE_RETRY宏,可能会引起我的兴趣,但是当我想要它时,我永远找不到它的文档.包括现在.

  • 谢谢,我在http://www.gnu.org/s/libc/manual/html_node/Interrupted-Primitives.html找到了宏的Docu,你知道有关锁定的futex()函数的一些信息吗? (2认同)
  • futex是一个特定于Linux的"轻等待"锁定框架,用于构建信号量和互斥量等更高级别的东西.见futex(7). (2认同)