Сбой приложения C++, включая dll ada, не создает дамп ядра
Вопрос
Как мне получить приложение C++, включающее загруженную общую библиотеку ada, для создания дампа ядра? при сбое?
У меня есть приложение C++, которое загружает общую библиотеку ada. Внутри кода ada я получаю ошибку переполнения стека, которая приводит к завершению программы вместе с выводом на консоль:
raised STORAGE ERROR
Файл дампа ядра не создается, даже если перед запуском приложения я ввел «ulimit -c неограниченный».
То же самое произойдет, если я отправлю убийство СИГСЕГВ в приложение.
Отправка убийства СИГСЕГВ другому приложению, которое не использует dll ada, генерирует файл дампа ядра именно так, как я хочу.
Нашел некоторую информацию здесь: http://objectmix.com/ada/301203-gnat-fstack-check-does-work.html
ОБНОВЛЕНО!Как отметил Адриан, противоречия нет, -с устанавливает предел стека, пока -с устанавливает лимит основного файла.
Тем не менее проблема остается.Я проверял флаги при сборке библиотеки ada и fstack-проверка флаг не был установлен, поэтому он должен создать дамп ядра.
Хотя я еще не пробовал, это кажется несколько странным.В нем упоминается опция компилятора -fstack-check + установка переменной GNAT_STACK_LIMIT, но в то же время ссылается на команду ulimit, которая кажется противоречием, установка «ulimit -c» - единственный известный мне способ создания дампа ядра. во время сбоя, если это следует из опции fstack-check, то у нас есть ловушка 22.
Решение
Теперь, почти 2 года спустя (все еще работая в той же компании, что и Кристофер, когда он задал этот вопрос), вопрос был поднят снова - и, наконец, я думаю, что понимаю, почему не создается дамп ядра!!
Проблема вызвана средой выполнения Ada, которая по умолчанию реализует обработчик некоторых POSIX-сигналов (для Linux:SIGABRT, SIGFPE, SIGILL, SIGSEGV и SIGBUS).Для GNAT/linux обработчик сигнала называется __gnat_error_handler в a-init.c, который выглядит примерно так:
static void
__gnat_error_handler (int sig)
{
struct Exception_Data *exception;
char *msg;
static int recurse = 0;
...
switch (sig)
{
case SIGSEGV:
if (recurse)
{
exception = &constraint_error;
msg = "SIGSEGV";
}
else
{
...
msg = "stack overflow (or erroneous memory access)";
exception = &storage_error;
}
break;
}
recurse = 0;
Raise_From_Signal_Handler (exception, msg);
}
Этот обработчик является «общим для всего процесса» и будет вызываться любым триггерным сигналом, независимо от того, из какой части процесса он исходит (независимо от того, закодирован ли он на Ada/C/C++...).
При вызове обработчик вызывает исключение Ada и оставляет его среде выполнения Ada для поиска подходящего обработчика исключений - если такой обработчик не найден (например.когда SIGSEGV генерируется какой-либо частью C++-кода), среда выполнения Ada просто завершает процесс и оставляет простую распечатку из __gnat_error_handler (например.«переполнение стека (или ошибочный доступ к памяти)»).
http://www2.adacore.com/gap-static/GNAT_Book/html/node25.htm
Чтобы запретить среде выполнения Ada обрабатывать сигнал POSIX и преобразовать его в исключение Ada, можно отключить поведение по умолчанию, используя
прагма Interrupt_State (Имя => значение, Состояние => СИСТЕМА | ВРЕМЯ ВЫПОЛНЕНИЯ | ПОЛЬЗОВАТЕЛЬ);,
например.чтобы отключить обработку SIGSEGV, определите
Pragma Interrupt_State(SIGSEGV, SYSTEM);
в вашем Ada-коде - теперь поведение системы по умолчанию будет запускаться при возникновении SIGSEGV, и будет создан дамп ядра, который позволит вам отследить источник проблемы!
Я думаю, что это очень важная проблема, которую следует учитывать при смешивании Ada и C/C++ на *NIX-платформах, поскольку это может ввести вас в заблуждение, полагая, что проблемы возникают из-за кода Ada (поскольку на распечатке указано исключение, сгенерированное Ada ), когда настоящий источник проблемы лежит в коде C/C++...
Хотя, вероятно, безопасно отключить обработку SIGSEGV по умолчанию во время выполнения Ada (я думаю, ни один здравомыслящий программист не будет использовать это для какой-либо «ожидаемой» обработки ошибок...Ну, возможно, используется в авиационном программном обеспечении или аналогичном, когда необходимо поддерживать какую-то «последнюю меру», чтобы избежать чего-то действительно плохого..) я думаю, следует проявить некоторую осторожность, а затем «переопределить» обработку во время выполнения Ada. для сигналов.
Одной из проблем может быть сигнал SIGFPE, который по умолчанию также вызывает исключение Ada Constraint_Error.Этот тип исключения может использоваться Ada-кодом как «ожидаемое поведение».Отключение SIGFPE с помощью Pragma Interrupt_State может серьезно повлиять на выполнение кода Ada и привести к сбою вашего приложения в «обычных обстоятельствах» - с другой стороны, любое деление на ноль в коде C/C++ запускает механизм обработки исключений Ada, и оставлю вас без каких-либо реальных следов происхождения проблемы...
Другие советы
Мне это кажется Действительно хорошее применение для вашего АдаКор поддерживать.Вы вряд ли найдете много людей за пределами этой компании, которые хорошо знакомы с последствиями взаимодействия между средой выполнения Gnu Ada и средой C++.
Я бы предложил для отладки кода Ada попробовать внедрить последний обработчик исключений вокруг всего, что, в свою очередь, сбрасывает стек исключений.У большинства поставщиков есть какой-то способ сделать это, обычно на основе Ada.Exceptions.Exception_Information и Ada.Exceptions.Exception_Message.
я нашел обсуждение с точки зрения безопасности (обнаружение вредоносного ПО).По сути, вы можете попробовать 10 сигналов: SIGSEGV
является лишь одним из них.
Кажется, вы можете просто позвонить sigaction(SIGSEGV, 0, SIG_DFL);
для восстановления поведения сигнала по умолчанию.