Подтвердить что ты не робот

Выберите EBADF: какой FD плохой?

У нас есть давняя ошибка в нашем производственном коде. Это, по сути, демон на базе сокета. Он прослушивает кучу filedescriptors, используя select.

Иногда (один раз в день или около того), выбор возвращается с помощью EBADF.

Я написал код для поиска плохого filedescriptor, который перебирает каждый fd и вызывает на нем выбор. Эти призывы никогда не возвращают EBADF. Я также пробовал fstat. Они также никогда не возвращают EBADF.

Я также переписал демона для использования опроса. Это не помогло.

Есть ли у кого-нибудь другие идеи? (кроме того, что я сделал тупая ошибка, с которой все легко сделать с выбором).

4b9b3361

Ответ 1

Я согласен с Джеймсом. С помощью poll() у вас есть осколки на fd, которые можно легко проверить.

т.е.

struct pollfd fds[NUM_FDS];
int ret, i;

...

ret = poll(fds, NUM_FDS, POLL_TIMEOUT);
for (i = 0; i < NUM_FDS; i++)
  if (fds[i].revents & POLLHUP || fds[i].revents & POLLNVAL)
     ... do something ...

Конечно, вы бы не реализовали его таким образом в реальном мире, это просто пример. Я прекратил использовать select() давно, poll() - гораздо лучший интерфейс. Вы правы, его слишком легко стрелять в ногу с помощью select().

Ответ 2

Скорее всего, select вызывается в закрытом дескрипторе файла. Обычным источником этого является повторное использование fd_set без повторной инициализации. У вас что-то происходит в обработчиках сигналов? (например, повторное открытие файла журнала на HUP?)

Ответ 3

Если вы используете poll(), вы можете просмотреть данные и посмотреть, с какой ошибкой fd, что является большим преимуществом.