Сбой приложения C++, включая dll ada, не создает дамп ядра

StackOverflow https://stackoverflow.com/questions/2236302

  •  19-09-2019
  •  | 
  •  

Вопрос

Как мне получить приложение 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); для восстановления поведения сигнала по умолчанию.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top