Ответ 1
Я столкнулся с той же проблемой; как отмечено выше, это завиток. Я думал, что отвечу здесь, чтобы собрать всю доступную информацию о проблеме.
libcurl, построенный без асинхронной библиотеки распознавателей, использует alarm() для тайм-аут DNS-запросов. Когда происходит тайм-аут, это приводит к тому, что libcurl перепрыгните из обработчика сигнала обратно в библиотеку с помощью sigsetjmp, что фактически приводит к тому, что libcurl продолжает работать в обработчик сигнала. Это не переносится и может вызвать проблемы на некоторых платформ. Обсуждение проблемы доступно на http://curl.haxx.se/mail/lib-2008-09/0197.html
"Проблемы на некоторых платформах", по-видимому, по крайней мере относятся к сбоям на современных Linux-системах. Некоторые более глубокие технические детали находятся по ссылке из приведенной выше цитаты:
Там проблема с тем, как libcurl в настоящее время обрабатывает SIGALRM сигнал. Он устанавливает обработчик для SIGALRM для принудительного синхронного DNS разрешить тайм-аут через определенное время, что является единственным способом прервать такое решение в некоторых случаях. Как раз перед разрешением DNS происходит инициализация указателя longjmp, поэтому, когда поступает сигнал в обработчике сигнала только siglongjmp, управление продолжается от это сохраненное местоположение, и функция возвращает код ошибки.
Проблема заключается в том, что выполняется весь следующий поток управления эффективно внутри обработчика сигнала. Не только существует риск того, что libcurl может вызвать ненадежную функцию async-обработчика (см. сигнал (7)) в течение этого времени, но он может вызвать функцию обратного вызова пользователя, которая мог бы назвать абсолютно что угодно. Фактически, siglongjmp() сам не включен список POSIX для асинхронных функций и что все libcurl вызовы обработчиков сигналов!
Есть несколько способов решить эту проблему, в зависимости от того, была ли вы построена libcurl или если вы застряли в том, что было предоставлено вашим дистрибутивом или системным администратором:
-
Если вы не можете перестроить libcurl, вы можете вызвать
curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1)
на всех ручках curl, которые вы используете. Документация дляCURLOPT_NOSIGNAL
отмечает:Пройдите длинный. Если это 1, libcurl не будет использовать какие-либо функции, которые устанавливать обработчики сигналов или любые функции, которые вызывают передачу сигналов к процессу. Эта опция в основном предназначена для многопоточного unix-приложения для установки/использования всех параметров таймаута и т.д., без рискуя получить сигналы. (Добавлено в 7.10)
Если этот параметр установлен, и libcurl был создан со стандартным name resolver, таймауты не будут возникать во время разрешения имени место. Подумайте о создании libcurl с поддержкой c-ares, чтобы асинхронные поисковые запросы DNS, которые обеспечивают приятные таймауты для имени разрешает без сигналов.
Тайм-ауты DNS, очевидно, желательно иметь в большинстве случаев, поэтому это не идеальное решение. Если у вас есть возможность перестроить libcurl в вашей системе, вы можете...
-
Существует асинхронная библиотека распознавателей DNS, называемая c-ares, которая зависает для разрешения имен. Использование этой библиотеки является предпочтительным решением проблемы (и я бы предположил, что большинство Linux-пакетов уже поняли это). Чтобы включить поддержку c-ares, сначала создайте и установите библиотеку, затем передайте флаг
--enable-ares
для завивкиconfigure
script перед созданием. Полные инструкции здесь.