У меня есть приложение 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 является сокетом.
Я мог бы добавить ограничение повторения к приведенному выше коду, но я хотел бы понять, что происходит в первую очередь.
В Linux выберите (2) может изменить Тайм-аут аргумент (передается по адресу). Поэтому вы должны скопировать его после звонка.
retry:
struct timeout timeoutcopy = timeout;
const int selectReturn
= ::select(fdMaxPlus1, readFDset, writeFDset, NULL, &timeoutcopy);
(в вашем коде ваш timeout
вероятно, ноль или очень мало после нескольких или даже первых итераций)
Кстати, я предлагаю скорее использовать Опрос (2) вместо select
(поскольку poll
С10К более дружественный к проблеме)
КСТАТИ, EINTR
происходит по любому сигналу (см. Сигнал (7)), даже без зарегистрированного обработчика сигнала.
Вы могли бы использовать strace
чтобы понять общее поведение вашей программы.