崩溃的 C++包含 ada dll 的应用程序不会生成核心转储

发布于 2024-08-20 21:47:42 字数 928 浏览 6 评论 0原文

如何让包含加载的 ada 共享库的 C++ 应用程序在崩溃时生成核心转储?

我有一个加载 ada 共享库的 C++ 应用程序,在 ada 代码内,我收到堆栈溢出错误,该错误导致程序终止以及控制台输出:

raised STORAGE ERROR

即使我发出了“ulimit -c unlimited”,也不会生成核心转储文件在开始应用程序之前。

如果我向应用程序发送终止 SIGSEGV ,也会发生同样的情况。

将kill SIGSEGV发送到另一个不使用ada dll的应用程序会按照我想要的方式生成一个核心转储文件。

在这里找到一些信息: http://objectmix.com/ada /301203-gnat-fstack-check-does-work.html

已更新! 正如Adrien所说,这并不矛盾,-s设置堆栈限制,而-c设置核心文件限制。

但问题仍然存在。我在构建 ada 库时检查了标志,并且未设置 fstack-check 标志,因此它应该生成核心转储。

虽然我还没尝试过,但似乎有些奇怪。 它提到了 -fstack-check 编译器选项+设置 GNAT_STACK_LIMIT 变量,但同时引用了 ulimit 命令,这似乎是矛盾的,设置“ulimit -c ”是我知道生成核心转储的唯一方法在崩溃时,如果这推断出 fstack-check 选项,那么我们就会遇到第 22 个问题。

How do I get a C++ application including a loaded ada shared library to generate a core dump when crashing?

I have a C++ application which loads a ada shared library, inside the ada code I get a stack overflow error which causes program termination along with the console output:

raised STORAGE ERROR

No core dump file is generated even thou I have issued a "ulimit -c unlimited" before starting the application.

Same thing happens if I send a kill SIGSEGV to the application.

Sending kill SIGSEGV to another application that does not use the ada dll generates a core dump file just the way I want it to.

Found some information here: http://objectmix.com/ada/301203-gnat-fstack-check-does-work.html

UPDATED!
As mentioned by Adrien, there is no contradiction, -s sets the stack limit while -c sets the core file limit.

Still the problem remains. I checked the flags when building the ada library and the fstack-check flag was not set, so it should generate a core dump.

Althou I haven't tried it yet, it seems somewhat strange.
It mentions the -fstack-check compiler option + setting the GNAT_STACK_LIMIT variable but at the same time refers to the ulimit command which seems like a contradiction, setting "ulimit -c " is the only way I know of getting a core dump to be generated at the time of crash, if this infers with the fstack-check option then we have a catch 22.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

迟到的我 2024-08-27 21:47:42

现在,差不多两年后(仍然与克里斯托弗提出问题时在同一家公司工作),这个问题再次被提出 - 最后我想我明白为什么没有生成核心转储!

该问题是由 Ada 运行时引起的,它默认为某些 POSIX 信号(对于 Linux:SIGABRT、SIGFPE、SIGILL、SIGSEGV 和 SIGBUS)实现信号处理程序。对于 GNAT/linux,信号处理程序在 a-init.c 中称为 __gnat_error_handler,看起来像这样:

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 运行时来查找适当的异常处理程序 - 如果未找到此类处理程序(例如,当 C++ 代码的任何部分生成 SIGSEGV 时),Ada -runtime 回退到仅终止进程并仅留下 __gnat_error_handler 的简单打印输出(例如“堆栈溢出(或错误的内存访问)”)。

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

为了防止 Ada 运行时处理 POSIX 信号,并将其转换为 Ada 异常,可以使用

pragma Interrupt_State (Name => value) 禁用默认行为,状态=>系统|运行时|用户);

例如。要禁用 SIGSEGV 的处理,请

Pragma Interrupt_State(SIGSEGV, SYSTEM);

在 Ada 代码中定义 - 现在,当引发 SIGSEGV 时,将触发系统的默认行为,并且将生成一个核心转储,使您能够追踪问题的根源!

我认为在 *NIX 平台上混合 Ada 和 C/C++ 时,这是一个非常重要的问题,因为它可能会误导您认为问题源于 Ada 代码(因为打印输出表明 Ada 生成了异常) )当问题的真正根源在于 C/C++ 代码时...

尽管禁用 SIGSEGV 的 Ada 运行时默认处理可能是安全的(我猜没有理智的程序员在任何“预期”错误处理中使用它。 .. 好吧,也许用在航空软件或类似软件中,当需要维护某种“最后手段”功能以避免发生真正糟糕的事情时..)我想应该谨慎一点,然后“覆盖”Ada-信号的运行时处理。

其中一个问题可能是 SIGFPE 信号,它默认也会引发 Ada Constraint_Error 异常。 Ada 代码可以将这种类型的异常用作“预期行为”。
通过 Pragma Interrupt_State 禁用 SIGFPE 可能会严重影响 Ada 代码的执行,并在“正常情况”期间使您的应用程序崩溃 - 另一方面,C/C++ 代码中的任何除零都会触发 Ada 异常处理机制,并且让你没有任何真正的线索来了解问题的根源......

Now, almost 2 years later (still working at the same company as Kristofer did when he asked the question), was the question raised again - and finally I think that I understands why no core-dump is generated!!

The problem is caused by the Ada run-time, which by default implements a signal handler for some POSIX-signals (for Linux: SIGABRT, SIGFPE, SIGILL, SIGSEGV and SIGBUS). For GNAT/linux the signal handler is called __gnat_error_handler in a-init.c, which looks something like this:

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);
 }

This handler is "process wide", and will be called by any trigged signal, no matter from which part of the process it originates from (no matter if coded in Ada/C/C++...).

When called, the handler rises an Ada-exception and leaves it to the Ada runtime to find an appropriate exception handler - if no such handler is found (eg. when an SIGSEGV is generated by any part of the C++-code), the Ada-runtime falls back to just terminate the process and just leave a simple printout from __gnat_error_handler (eg. "stack overflow (or erroneous memory access)").

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

To prevent Ada-runtime from handling a POSIX-signal, and convert it to an Ada-exception, it is possible to disable the default beahviour by using

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

eg. to disable handling of SIGSEGV, define

Pragma Interrupt_State(SIGSEGV, SYSTEM);

in your Ada-code - now the system's default behaviour will be trigged when a SIGSEGV is raised, and a core-dump will be generated that allows you to trace down the origin of the problem!

I think this is a quite important issue to be aware of when mixing Ada and C/C++ on *NIX-platforms, since it may mislead you to think that problems origins from the Ada-code(since the printout indicates an exception generated from Ada) when the real source of the problem lays in the C/C++-code...

Although it is probably safe to disable the Ada-runtime default handling of SIGSEGV (I guess no sane programmer using this in any "expected" error handling... Well, maybe used in aviation software or similar, when some sort of "last resort" functionallity needs to be maintained to avoid something really bad from happening..) i guess a bit caution should be taken then "overriding" the Ada-runtime handling for signals.

One issue may be the SIGFPE-signal, which also raises an Ada Constraint_Error-exception by default. This type of exception may be used by the Ada-code as an "excpected behaviour".
Disabling SIGFPE by Pragma Interrupt_State may seriously affect the execution of the Ada-code, and crash your application during "normal circumstances" - on the other hand will any division by zero in the C/C++-code trig the Ada-exception handling mechanism, and leave you without any real trace of the origin of the problem...

几度春秋 2024-08-27 21:47:42

在我看来,这对于您的 AdaCore 支持来说确实很有用。您不可能在该公司之外找到很多熟悉 Gnu Ada 运行时和 C++ 运行时之间交互含义的人。

我建议在调试 Ada 代码时,尝试在所有内容周围放入一个最后的异常处理程序,这反过来会转储异常堆栈。大多数供应商都有某种方法可以做到这一点,通常基于 Ada.Exceptions.Exception_Information 和 Ada.Exceptions.Exception_Message。

This looks to me like a really good use for your AdaCore support. You aren't liable to find a whole lot of folk outside that company who are that familiar with the implications of the interactions between Gnu Ada's runtime and C++'s.

I would suggest for debugging the Ada code that you try putting in a last-ditch exception handler around everything, which in turn dumps the exception stack. Most vendors have some way of doing that, usually based off of Ada.Exceptions.Exception_Information and Ada.Exceptions.Exception_Message.

濫情▎り 2024-08-27 21:47:42

我发现讨论来自安全视角(查找恶意软件)。基本上有 10 个信号可以尝试,SIGSEGV 只是其中之一。

I found a discussion from a security perspective (finding malware). Basically there are 10 signals that you can try, SIGSEGV is only one of them.

固执像三岁 2024-08-27 21:47:42

看来您可以简单地调用 sigaction(SIGSEGV, 0, SIG_DFL); 来恢复默认信号行为。

It seems you can simply call sigaction(SIGSEGV, 0, SIG_DFL); to restore the default signal behavior.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文