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

我的用户空间应用程序有时会在收到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

我可以捕获EINTR信号吗,如何重复有关的调用,例如写入,读取或选择?即使使用与系统调用一起使用的第三方库,我如何确定EINTR发生在哪里?

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

谢谢

回答:

调用写(或其他阻止操作)的代码必须知道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

或者对于表现得更好的东西,它重试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

GNU有一个可能不感兴趣的非标准TEMP_FAILURE_RETRY宏,尽管当我想要它们时,我永远也找不到它的文档。包括现在。

以上是 如何处理EINTR(系统调用中断) 的全部内容, 来源链接: utcz.com/qa/416037.html

回到顶部