gpt4 book ai didi

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

转载 作者:IT王子 更新时间:2023-10-29 01:02:41 25 4
gpt4 key购买 nike

我的用户空间应用程序有时会以某种方式在收到 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 dump:我发送了一个 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 宏,尽管我永远找不到它的文档。包括现在。

关于c++ - 如何处理EINTR(系统调用中断),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1674162/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com