gethostbyname/getaddrinfo продолжает сбой, даже когда интернет-соединение установлено
Фон
У нас есть небольшой безголовый бокс с ядром Linux 2.6.35 и некоторым вариантом дистрибутива Open Embedded на оборудовании ARM.
Насколько мы можем судить, мы используем glibc 2.10.1.
Коробка имеет неподключенный Ethernet и последовательный модем GSM/3G. Мы настроили PPP, чтобы обеспечить постоянное подключение к Интернету. Эта часть работает без проблем.
У нас есть программа, написанная на c (на самом деле C++), которая устанавливает соединение с использованием сокетов. Программа сильно многопоточная с использованием pthreads.
Для поиска IP-адреса для подключения мы используем gethostbyname().
Когда нет подключения к Интернету, например, во время начальной загрузки или когда SIM-карта извлечена из модема, gethostbyname() возвращает NULL, как и должно быть.
Симптом
Но иногда gethostbyname () продолжает возвращать NULL, даже если интернет-соединение установлено.
Код ошибки от getaddrinfo() при использовании, это EAI_NONAME ~ "Имя или служба неизвестна". У нас нет кода ошибки из gethostbyname (), но он был эквивалентен.
Наш анализ
Мы убедились, что интернет-соединение в порядке (через последовательную консоль)
- Элемент списка
- Просматривая /var/log/messages и убедившись, что pppd говорит, что все в порядке
- ping имя хоста (переводит в IP и отвечает нормально)
- подключиться к коробке через ssh через публичный IP
У нас есть два потока в процессе, которые используют gethostbyname () для одного хоста. Они имеют слегка отличающиеся пути кода и функции, но используют общий код для функций сокета, включая часть, которая вызывает gethostbyname().
В ситуациях, когда gethostbyname () продолжает возвращать NULL, это обычно верно только для ОДНОГО из потоков, а не один и тот же каждый раз. Другой делает поиск идеально.
Кроме того, поток с ошибкой gethostbyname () может быть легко приведен в действие путем простого контролируемого останова этого потока и перезапуска функции, что в результате приведет к созданию нового потока в обратном порядке.
В целом мы убеждены, что трансляция DNS и подключение к интернету работают нормально на уровне ОС.
Чтобы исключить проблемы с многопоточностью, мы повторно реализовали код поиска, используя getaddrinfo(), который повторно вводится в соответствии со страницей руководства. И с точно таким же результатом.
Нам кажется, что выход из потока приводит к некоторой очистке, которая влияет на способность gethostbyname()/getaddrinfo() выполнять поиск.
Обходным путем может быть принудительное завершение выходящего из строя потока, но это будет означать существенное изменение структуры приложения и на самом деле не вариант.
Вопрос
Итак, вопрос: есть ли у вас какие-либо указания, где искать решение или где может быть настоящая проблема?
1 ответ
char *hostname = "www.example.com";
struct hostent *a_server;
a_server=gethostbyname(hostname);
while (a_server == NULL) {
a_server=gethostbyname(hostname);
sleep(1);
}