为什么select()总是以EINTR错误号失败

Why does select() keep failing with EINTR errno?

本文关键字:EINTR 错误 失败 select 为什么      更新时间:2023-10-16

我有一个C++应用程序,它包含以下函数:

int
mySelect(const int fdMaxPlus1,
         fd_set *readFDset,
         fd_set *writeFDset,
         struct timeval *timeout)
{
 retry:
  const int selectReturn
    = ::select(fdMaxPlus1, readFDset, writeFDset, NULL, timeout);
  if (selectReturn < 0 && EINTR == errno) {
    // Interrupted system call, such as for profiling signal, try again.
    goto retry;
  }
  return selectReturn;
}

通常情况下,这段代码工作得很好,但在一个例子中,我看到它进入了一个无限循环,select()EINTRerrno代码一直在失败。在这种情况下,调用者将超时设置为0秒零微秒,这意味着不要等待并立即返回select()结果。我认为EINTR只在发生信号处理程序时发生,为什么我会一次又一次地(超过12个小时)得到信号处理程序?这是Centos 5。一旦我将其放入调试器中查看发生了什么,经过几次迭代后,代码返回时没有EINTR。请注意,要检查的fd是一个套接字。

我可以在上面的代码中添加重试限制,但我想先了解一下发生了什么。

在Linux上,select(2)可以修改timeout参数(通过地址传递)。所以你应该在通话后复印。

retry:
struct timeout timeoutcopy = timeout;
const int selectReturn
  = ::select(fdMaxPlus1, readFDset, writeFDset, NULL, &timeoutcopy);

(在您的代码中,经过几次甚至第一次迭代后,timeout可能为零或非常小)

顺便说一句,我建议使用poll(2)而不是select(因为poll对C10K问题更友好)

BTW,EINTR发生在任何信号上(参见信号(7)),即使没有注册的信号处理程序。

您可以使用strace来了解程序的整体行为。