使用 JNA 使用本机 fortran 库时查找 SIGSEGV 原因的问题
Posted
技术标签:
【中文标题】使用 JNA 使用本机 fortran 库时查找 SIGSEGV 原因的问题【英文标题】:Problems finding the cause of SIGSEGV while using a native fortran library using JNA 【发布时间】:2017-01-20 14:39:21 【问题描述】:我正在使用 JNA
与来自 Java/Scala 的本机 Fortran 库(物理)交互,使用 Apache Spark 分布式计算框架调用。
以下报告是使用我的库/opt/MYORG/hdd/usr/local/lib/mylib.so
生成的,该库使用ifort
和调试编译器选项编译
-shared -fPIC -save -g -check all -fpe0 -traceback -static -static-intel -Bstatic
由于SIGSEGV
,我的执行程序不时崩溃,JVM 错误报告表明:
#
# A fatal error has been detected by the Java Runtime Environment:
#
# SIGSEGV (0xb) at pc=0x00007fea0f490700, pid=33080, tid=140647778658048
#
# JRE version: Java(TM) SE Runtime Environment (8.0_60-b27) (build 1.8.0_60-b27)
# Java VM: Java HotSpot(TM) 64-Bit Server VM (25.60-b23 mixed mode linux-amd64 compressed oops)
# Problematic frame:
# C 0x00007fea0f490700
完整的报告在这里上传:https://www.amazon.com/clouddrive/share/GDqXyIRNVkY86XYCXkorjiuE4bZm4AmnNWllXBhMVmk?encoding=UTF8&mgh=1&ref=cd_ph_share_link_copy
我设法创建了一个核心转储,我用
对其进行了分析gdb /usr/java/jdk1.8.0_60/bin/java core.33080
(gdb) bt
#0 0x00007fed0a04f1d7 in raise () from /usr/lib64/libc.so.6
#1 0x00007fed0a0508c8 in abort () from /usr/lib64/libc.so.6
#2 0x00007fed0995b6b5 in os::abort(bool) () from /usr/java/jdk1.8.0_60/jre/lib/amd64/server/libjvm.so
#3 0x00007fed09af9bf3 in VMError::report_and_die() () from /usr/java/jdk1.8.0_60/jre/lib/amd64/server/libjvm.so
#4 0x00007fed09960edf in JVM_handle_linux_signal () from /usr/java/jdk1.8.0_60/jre/lib/amd64/server/libjvm.so
#5 0x00007fed09957673 in signalHandler(int, siginfo*, void*) () from /usr/java/jdk1.8.0_60/jre/lib/amd64/server/libjvm.so
#6 <signal handler called>
#7 0x00007fea0f490700 in ?? ()
#8 0x00007fed0a7fcbc2 in __nptl_deallocate_tsd () from /usr/lib64/libpthread.so.0
#9 0x00007fed0a7fcdd3 in start_thread () from /usr/lib64/libpthread.so.0
#10 0x00007fed0a11173d in clone () from /usr/lib64/libc.so.6
我用
进一步分析了核心thread apply all bt full
(输出可以在这里找到:https://www.amazon.com/clouddrive/share/ZUmv6GEM2oJ0MCCqfnNEs2OOateJVGnhnxoHsJnbvBV?ref_=cd_ph_share_link_copy)
但我没有看到当前在我自己的(可能有故障的)库mylib.so
中的任何线程,所有线程似乎都在等待。到目前为止,我没有指出 mylib.so
导致 SIGSEGV
的事实,但是如果我在代码中用 Mock 替换对 mylib.so
的调用(即没有实际的本机调用),则不会出现 SIGSEGV
,因此我的结论是问题一定出在对我的本地库的 JNA 调用中。
到目前为止,我尝试了以下提示:https://software.intel.com/en-us/articles/determining-root-cause-of-sigsegv-or-sigbus-errors 没有成功
有人可以帮我找出上述SIGSEGV
的原因吗?
【问题讨论】:
你可能不想要-dynamic
和-static
(你应该放弃后者,但这有时会因平台而异)。
@technomage 我在哪里使用-dynamic
?
我担心你的 Fortran 库几乎可以有任何东西。你确定它没有错误吗?
FWIW 您的错误报告表明错误线程试图执行数据 - 指令指针 (RIP) 没有引用代码页。这可能是由于堆栈损坏 - 堆栈上的返回指令指针,在过程结束时引用,已被丢弃。堆栈和基指针 (RSP/RBP) 的不一致以及缺乏连贯的堆栈跟踪也表明堆栈损坏。在 Fortran 中要查找的内容包括(像往常一样)数组边界违规或过程调用和定义之间的接口不匹配。
抱歉,我指的是-shared
,而不是-dynamic
。
【参考方案1】:
这种错误是相当讨厌的。您可以尝试应用以下模式:
https://github.com/mkowsiak/jnicookbook/tree/master/recipes/recipeNo015
在这种方法中,您可以在代码中“捕获”SIGSEGV。然后,您可以尝试使用 backtrace 函数获取回溯:
void *array[100];
size_t size;
size = backtrace (array, 100);
backtrace_symbols_fd (array, size, STDOUT_FILENO);
请注意,您不应在信号处理程序内部做太多事情。
然后,如果运气好,您将能够找出问题的原因。
另一种方法是使用 gdb 实际调试 JVM,看看那里会发生什么。
您可以在此处找到 JNI 调试示例:
http://www.owsiak.org/?p=2095
或这里:
https://github.com/mkowsiak/jnicookbook/tree/master/recipes/recipeNoD001
或这里:
https://youtu.be/8Cjeq4l5COU
如前所述,尝试在 Fortran 代码中启用边界检查。有时会有所帮助。
我希望它会有所帮助。
享受 JNI/JNA 的乐趣。
【讨论】:
您的第一个链接已失效。下次请考虑在答案中总结解决方案,而不是只提供外部链接。以上是关于使用 JNA 使用本机 fortran 库时查找 SIGSEGV 原因的问题的主要内容,如果未能解决你的问题,请参考以下文章
在Linux环境下使用gfortran编译器生成fortran语言的.so共享对象文件 并使用JNA调用 带参方法