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

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

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

raised STORAGE ERROR

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

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

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

Нашел некоторую информацию здесь: 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.


person Kristofer    schedule 10.02.2010    source источник
comment
в упомянутой выше статье речь идет о ulimit -s, который сильно отличается от ulimit -c, поэтому я не вижу противоречия с настройками компилятора ...   -  person Adrien Plisson    schedule 10.02.2010
comment
aplawrence.com/Linux/limit_core_files.html   -  person Martin York    schedule 10.02.2010


Ответы (4)


Теперь, почти 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 -runtime возвращается, чтобы просто завершить процесс и оставить простую распечатку из __gnat_error_handler (например, «переполнение стека (или ошибочный доступ к памяти)»).

http://www2.adacore.com/gap-static/GNAT_Book/html/node25.htm

Чтобы предотвратить обработку POSIX-сигнала во время выполнения Ada и преобразовать его в исключение Ada, можно отключить поведение по умолчанию, используя

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

например. чтобы отключить обработку 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, и оставим вас без каких-либо реальных следов происхождения проблемы ...

person Stefan Andersson    schedule 22.10.2012

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

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

person T.E.D.    schedule 10.02.2010

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

person MSalters    schedule 11.02.2010
comment
Спасибо, я постараюсь отправить их все, чтобы проверить, отличается ли результат. - person Kristofer; 11.02.2010
comment
Я проверил все 10, все они генерируют дамп ядра в чистом приложении c ++, в то время как дамп ядра создается только в приложении c ++ / ada для следующих сигналов: SIGQUIT, SIGSYS, SIGTRAP, SIGXCPU, SIGXFSZ. Остальные вызывают либо возникновение PROGRAM_ERROR, CONSTRAINT_ERROR, либо STORAGE_ERROR. - person Kristofer; 11.02.2010
comment
Нет, проблема остается, приложение все еще находится в разработке, и новые ошибки, вызывающие SIGSEGV, вероятно, будут введены / найдены в какой-то момент, именно в этих случаях я хочу, чтобы дамп ядра создавался автоматически. - person Kristofer; 12.02.2010
comment
А, тогда ты можешь перефразировать свой вопрос. Я понял, что вы хотели намеренно сделать дамп ядра приложения извне. - person MSalters; 12.02.2010

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

person MSalters    schedule 12.02.2010