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

Error: longjmp вызывает неинициализированную стек кадров

У меня есть серверное приложение, которое создает шину на dbus, и через несколько минут работы у меня появилась ошибка, которую я никогда раньше не видел. У вас есть идея, что не так?

*** longjmp causes uninitialized stack frame ***: /home/user/Workspace/DBus_Server/Debug/DBus_Server terminated
======= Backtrace: =========
/lib/x86_64-linux-gnu/libc.so.6(__fortify_fail+0x37)[0x7f8d8911c7f7]
/lib/x86_64-linux-gnu/libc.so.6(+0xf8789)[0x7f8d8911c789]
/lib/x86_64-linux-gnu/libc.so.6(__longjmp_chk+0x33)[0x7f8d8911c6f3]
/usr/lib/x86_64-linux-gnu/libcurl-nss.so.4(+0xd795)[0x7f8d88272795]
/lib/x86_64-linux-gnu/libc.so.6(+0x36420)[0x7f8d8905a420]
/lib/x86_64-linux-gnu/libc.so.6(__poll+0x53)[0x7f8d890f9773]
/usr/lib/libdbus-c++-1.so.0(_ZN4DBus15DefaultMainLoop8dispatchEv+0x161)[0x7f8d89b6b481]
/usr/lib/libdbus-c++-1.so.0(_ZN4DBus13BusDispatcher5enterEv+0x63)[0x7f8d89b6c293]
/home/user/Workspace/DBus_Server/Debug/DBus_Server[0x401333]
/lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xed)[0x7f8d8904530d]
/home/user/Workspace/DBus_Server/Debug/DBus_Server[0x4011c9]
4b9b3361

Ответ 1

Я столкнулся с той же проблемой; как отмечено выше, это завиток. Я думал, что отвечу здесь, чтобы собрать всю доступную информацию о проблеме.

Из отчет об ошибке Red Hat:

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 перед созданием. Полные инструкции здесь.

Ответ 2

Это должно быть исправлено в curl 7.32.0 в соответствии с Debian changelog, где реализован поточный DNS-резольвер. Пакет Debian нестабилен и его можно найти здесь.

Для Ubuntu 12.04 → 13.04 вы можете использовать этот PPA.

sudo apt-add-repository ppa:jaywink/curldebian
sudo apt-get update && sudo apt-get upgrade

Ubuntu 13.10 включает curl 7.32, поэтому не должно быть этой проблемы.