Сбой приложения C ++, включая ada dll, не генерирует дамп ядра - PullRequest
0 голосов
/ 10 февраля 2010

Как получить приложение C ++, включая загруженную общую библиотеку ada, для создания дампа ядра при сбое ?

У меня есть приложение C ++, которое загружает общую библиотеку ada, внутри кода ada я получаю ошибку переполнения стека, которая вызывает завершение программы вместе с выводом на консоль:

raised STORAGE ERROR

Файл дампа основной памяти не создается, даже если я перед запуском приложения выдал «ulimit -c unlimited».

То же самое происходит, если я посылаю в приложение kill SIGSEGV .

Отправка kill SIGSEGV в другое приложение, которое не использует ada dll, создает файл дампа ядра так, как я этого хочу.

Нашел некоторую информацию здесь: http://objectmix.com/ada/301203-gnat-fstack-check-does-work.html

ОБНОВЛЕНО! Как упоминал Адриен, в этом нет никакого противоречия: -s устанавливает ограничение стека, в то время как -c устанавливает ограничение файла ядра.

Тем не менее проблема остается. Я проверял флаги при сборке библиотеки ada и флаг fstack-check не был установлен, поэтому он должен генерировать дамп ядра.

Хотя я еще не пробовал, это кажется несколько странным. В нем упоминается опция компилятора -fstack-check + установка переменной GNAT_STACK_LIMIT, но в то же время ссылается на команду ulimit, которая выглядит как противоречие, установка «ulimit -c» - единственный известный мне способ получения дампа ядра во время сбоя, если это связано с опцией fstack-check, то у нас есть ловушка 22.

Ответы [ 4 ]

6 голосов
/ 22 октября 2012

Теперь, почти через 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-runtime обрабатывать POSIX-сигнал и преобразовать его в Ada-исключение, можно отключить beahviour по умолчанию с помощью

pragma Interrupt_State (Name => value, State => SYSTEM | RUNTIME | USER); ,

например. чтобы отключить обработку SIGSEGV, определите

Pragma Interrupt_State(SIGSEGV, SYSTEM);

в вашем Ада-коде - теперь поведение системы по умолчанию будет срабатывать при поднятии SIGSEGV, и будет сгенерирован дамп ядра, который позволит вам отследить источник проблемы!

Я думаю, что это очень важная проблема, о которой следует помнить при смешивании Ada и C / C ++ на * NIX-платформах, так как это может ввести вас в заблуждение, что проблемы возникают из-за кода Ada (поскольку распечатка указывает на исключение генерируется из Ada), когда реальный источник проблемы лежит в C / C ++ - код ...

Хотя, вероятно, безопасно отключить обработку SIGSEGV по умолчанию во время выполнения Ada (я думаю, ни один здравомыслящий программист не использовал бы это в какой-либо "ожидаемой" обработке ошибок ... Ну, может быть, используется в авиационном программном обеспечении или подобном, когда какой-то Функциональность "последней инстанции" должна поддерживаться, чтобы избежать чего-то действительно плохого ...) Я думаю, что нужно быть немного осторожнее, чтобы затем "переопределить" обработку Ada-runtime для сигналов.

Одной из проблем может быть сигнал SIGFPE, который также вызывает исключение Ada Constraint_Error по умолчанию. Этот тип исключения может использоваться Ада-кодом как «ожидаемое поведение». Отключение SIGFPE с помощью Pragma Interrupt_State может серьезно повлиять на выполнение Ada-кода и привести к сбою приложения в «нормальных обстоятельствах» - с другой стороны, любое деление на ноль в C / C ++ - код вызовет механизм обработки Ada-исключений, и оставить вас без каких-либо реальных следов происхождения проблемы ...

1 голос
/ 10 февраля 2010

Это выглядит как действительно хорошее использование для поддержки AdaCore . Вы не обязаны находить много людей за пределами этой компании, которые хорошо знакомы с последствиями взаимодействия между средой выполнения Gnu Ada и C ++.

Я бы предложил для отладки кода Ada, который вы пытаетесь поместить в обработчик исключений последней очереди вокруг всего, что, в свою очередь, сбрасывает стек исключений. У большинства поставщиков есть такой способ, обычно основанный на Ada.Exceptions.Exception_Information и Ada.Exceptions.Exception_Message.

0 голосов
/ 12 февраля 2010

Кажется, вы можете просто позвонить sigaction(SIGSEGV, 0, SIG_DFL);, чтобы восстановить поведение сигнала по умолчанию.

0 голосов
/ 11 февраля 2010

Я нашел обсуждение с точки зрения безопасности (поиск вредоносного ПО). По сути, вы можете попробовать 10 сигналов, SIGSEGV - только один из них.

...