我有一个包含此功能的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()
使EINTR
errno
代码失败。在这种情况下,调用者将超时设置为零秒和零微秒,这意味着不要等待并立即返回select()
结果。我认为EINTR
仅在信号处理程序发生时才会发生,为什么我会一遍又一遍地使用信号处理程序(超过12小时)?这是Centos 5.一旦我把它放到调试器中看看发生了什么,代码在几次迭代后没有EINTR就返回了。请注意,正在检查的fd是套接字。
我可以为上面的代码添加重试限制,但我想先了解一下发生了什么。
答案 0 :(得分:1)
在Linux上,select(2)可能会修改 timeout 参数(通过地址传递)。所以你应该在通话后复制它。
retry:
struct timeout timeoutcopy = timeout;
const int selectReturn
= ::select(fdMaxPlus1, readFDset, writeFDset, NULL, &timeoutcopy);
(在您的代码中,您的timeout
在经过几次甚至是第一次迭代后可能为零或非常小)
select
(因为poll
更多是C10K问题友好)
BTW,EINTR
发生在任何信号上(见signal(7)),即使没有注册信号处理程序。
您可以使用strace
来了解程序的整体行为。