java - 为什么我在 JVM 下运行时在我的 Ada 共享库上得到 "storage error"

标签 java linux segmentation-fault ada gnat

我们有一个由 GnatPro 19.2 编译的 Ada 共享库,我们通过 JNA 调用来调用它。

我们的应用程序在 Windows 下运行良好。在 Linux 下移植时,应用程序随机崩溃并出现 Ada 异常:

storage error or erroneous memory access.

使用 gdb 调试(附加进程)没有多大帮助。我们收到各种 SIGSEGV,我们继续,过了一会儿,我们收到存储错误,没有可用的调用堆栈。

我们的共享库可以与 python native 调用一起使用,没有任何问题。问题可能出在 Java 方面。

尝试切换 JVM(openjdk 或官方 jdk),但没有成功。

这是为什么?有解决办法吗?

最佳答案

第一个提示是在尝试将调试器附加到应用程序时获得一堆 SIGSEGV,然后在继续时看到程序恢复。

这意味着 SIGSEGV 信号是在 Java 端处理的,正如 Why does java app crash in gdb but runs normally in real life? 中所确认的。 .

Java uses speculative loads. If a pointer points to addressable memory, the load succeeds. Rarely the pointer does not point to addressable memory, and the attempted load generates SIGSEGV ... which java runtime intercepts, makes the memory addressable again, and restarts the load instruction.

现在会发生什么,默认情况下,GNAT 运行时会安装一个 new 信号处理程序来捕获 SIGSEGV 并重定向到一个干净的 Ada 异常。 Ada 异常的一个有趣特性是它们可以打印堆栈跟踪,即使没有调试器。这个 SIGSEGV 处理程序重定向允许这样做。

但在 Java 的情况下,由于 Java 使用推测加载,因此 Java 端不时需要 SIGSEGV。因此,当 Ada 共享库被加载和初始化后,Ada SIGSEGV 处理程序被安装,并捕获那些“正常”的 SIGSEGV,并立即中止。

请注意,它不会在 Windows 下发生。由于 Windows 在处理内存违规访问时的限制,java 运行时可能无法使用这种推测加载机制。

信号处理在s-intman.adb

中完成
 --  Check that treatment of exception propagation here is consistent with
  --  treatment of the abort signal in System.Task_Primitives.Operations.

  case signo is
     when SIGFPE  => raise Constraint_Error;
     when SIGILL  => raise Program_Error;
  --   when SIGSEGV => raise Storage_Error;  -- commenting this line should fix it
     when SIGBUS  => raise Storage_Error;
     when others  => null;
  end case;
end Notify_Exception;

现在我们必须重新构建一个新的 native 运行时并使用它来代替默认运行时。这是相当乏味且容易出错的。该文件是 gnarl 库的一部分。我们必须使用正确的选项动态重建 gnarl 库 -gnatp -nostdinc -O2 -fPIC 以创建 gnatrl 库替换...并在升级编译器时再次执行此操作...

幸运的是,AdaCore 提供了另一种解决方案:

首先在.gpr项目目录中创建一个pragmas文件(我们称之为no_sigsegv.adc)包含:

pragma Interrupt_State (SIGSEGV, SYSTEM); 

指示运行时不要安装 SIGSEGV 处理程序

然后将这个添加到.gpr文件的Compiler包中:

  package Compiler is
    ...
      for local_configuration_pragmas use Project'Project_dir & "/no_sigsegv.adc";

从头开始重建一切。测试:没有任何一次崩溃。

关于java - 为什么我在 JVM 下运行时在我的 Ada 共享库上得到 "storage error",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62672924/

相关文章:

c++ - 处理迭代器时由信号 SIGSEGV(地址边界错误)终止

c - (C) 传递给 func 的指针与原始指针不同

java - JDK 7(Mac OS)中的 libjsig.so 在哪里?

linux - 带有 CTI 端口的 JTAPI 可与 Cisco Unified Call Manager 8.5 版集成

php - 在 PHP 中以用户身份执行 Linux 命令

Linux 上的 Python 远程连接到 Windows PC 以检索文件

c++ - 实例化结构时出现段错误 - C++

java - 如何在 Eclipse 中自动修复 "The declared package does not match..."错误?

java - Tomcat - 部署应用程序 - 数据源问题

java - Spring 的 ObjectFactoryCreatingFactoryBean 可以与引用接口(interface)的泛型一起工作吗?