Почему select () продолжает работать с ошибкой EINTR errno?

У меня есть приложение 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 является сокетом.

Я мог бы добавить ограничение повторения к приведенному выше коду, но я хотел бы понять, что происходит в первую очередь.

2

Решение

В Linux выберите (2) может изменить Тайм-аут аргумент (передается по адресу). Поэтому вы должны скопировать его после звонка.

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

(в вашем коде ваш timeout вероятно, ноль или очень мало после нескольких или даже первых итераций)

Кстати, я предлагаю скорее использовать Опрос (2) вместо select (поскольку poll С10К более дружественный к проблеме)

КСТАТИ, EINTR происходит по любому сигналу (см. Сигнал (7)), даже без зарегистрированного обработчика сигнала.

Вы могли бы использовать strace чтобы понять общее поведение вашей программы.

0

Другие решения


По вопросам рекламы [email protected]