Выберите EBADF: какой FD плохой?
У нас есть давняя ошибка в нашем производственном коде. Это, по сути, демон на базе сокета. Он прослушивает кучу filedescriptors, используя select.
Иногда (один раз в день или около того), выбор возвращается с помощью EBADF.
Я написал код для поиска плохого filedescriptor, который перебирает каждый fd и вызывает на нем выбор. Эти призывы никогда не возвращают EBADF. Я также пробовал fstat. Они также никогда не возвращают EBADF.
Я также переписал демона для использования опроса. Это не помогло.
Есть ли у кого-нибудь другие идеи? (кроме того, что я сделал тупая ошибка, с которой все легко сделать с выбором).
Ответы
Ответ 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, что является большим преимуществом.