问题描述
我在运行于Wind River Linux的嵌入式系统上工作.
I work on an embedded system running on Wind River Linux.
它是Java和C ++的结合,带有一些用于技术之间通信的JNI.
It is a mix of Java and C++ with some JNI for communication between technologies.
我们已经建立了自定义错误处理功能,以便在发生任何意外错误时,我们可以生成回溯记录和其他信息来帮助我们确定问题.
We have build custom error handling so that in the event of any unexpected errors we generate backtraces and other information to help us determine the problem.
此错误处理始终由所有其他组件都必须向其注册的C ++组件完成(以便可以安装适当的信号处理程序).
This error handling is always done by a C++ component that all other components must register with (so that the appropriate signals handlers can be installed).
因此,对于Java组件,我们使用JNI与C ++错误处理程序进行通信.
So in the case of a Java component we use JNI to communicate with the C++ error hander.
我们的测试程序使用35种不同的场景来测试所有各种类型的错误(内存不足,未处理的异常,访问冲突,堆栈溢出等).这是针对单个主线程案例和后台线程完成的.
Our test program uses 35 different scenario's to test all the various types of errors (out of memory, unhandled exceptions, access violations stackoverflows, etc) This is done for both a single main thread case and background threads.
除在JNI主线程和后台线程中引起的Stackoverflow外,所有测试均正常工作.
All tests work properly with the exception of a Stackoverflow caused in a JNI main thread and background thread.
在Linux上,Stackoverflow应生成SIGSEGV,并应调用已安装的sigaction.但是相反,我们只是终止了,即未调用处理程序.
On Linux a Stackoverflow should generate a SIGSEGV and the installed sigaction should be invoked. But instead we are simply terminating, i.e. the handler does not get called.
如果我们直接生成一个SIGSEGV(信号11)而不是生成stackoverflow,则信号处理程序的确会正确调用.
If instead of generating a stackoverflow, we directly cause a SIGSEGV (signal 11), our signal handler does get invoked properly.
请注意,我们还对提供的libjsig.so在Oracle(Java)上执行了LD_PRELOAD,据称这是在使用JNI时正确安装自定义信号处理程序所必需的(如果未完成,则其他测试用例会失败).
Note that we also do a LD_PRELOAD on the Oracle (Java) provided libjsig.so, this is supposedly required to correctly install custom signal handlers when using JNI (and if not done, other test cases fail).
奇怪的是,如果我在没有LD_PRELOAD的情况下运行测试,则在这种情况下确实会调用信号处理程序.
Strangely, if I run the test without the LD_PRELOAD, the signal handler does get invoked for this case.
寻找有关如何调试或解决此问题的想法
Looking for ideas on how to debug or solve this problem
推荐答案
当我不得不编写JNI代码来处理SIGSEGV
等时-我的代码不得不清理某些文件状态关于异常终止-我发现仅手动链接SIGABRT
处理程序而根本不使用libjsig.so
会更容易. JVM似乎总是以SIGABRT
异常终止-我会导致致命的SIGSEGV
,JVM会处理该致命的SIGSEGV
并将其转换为SIGABRT
.我做什么都不重要.
When I had to write JNI code to handle SIGSEGV
et al - I had code that had to clean up some file state on abnormal termination - I found it easier to just manually chain a SIGABRT
handler and not use libjsig.so
at all. The JVM always seemed to terminate abnormally with a SIGABRT
- I'd cause a fatal SIGSEGV
, which the JVM would handle and translate to a SIGABRT
. It didn't seem to matter what I did.
我现在无法在Oracle文档中找到它,但是 IBM文档因此对JVM信号进行了处理:
I can't find it in the Oracle documentation right now, but IBM documents JVM signal handling thus:
如果JVM检测到无法恢复的条件,则会引发SIGABRT
.
The JVM raises a SIGABRT
if it detects a condition from which it cannot recover.
我的代码的一个版本(为消除滚动条而缩写):
A version of my code (abbreviated in order to eliminate the scroll bar):
typedef void ( *sigaction_handler_t )( int, siginfo_t *, void * );
static sigaction_handler_t original_sigabort_handler = NULL;
static void handler( int sig, siginfo_t *info, void *arg )
{
switch ( sig )
{
case SIGABRT:
//do stuff - stack trace, setrlimit() to generate core file, etc.
if ( NULL != original_sigabort_handler )
{
original_sigabort_handler( sig, info, arg );
}
break;
default:
break;
}
}
__attribute(( constructor )) void library_init_code( void )
{
struct sigaction new_act, old_act;
memset( &new_act, 0, sizeof( new_act );
memset( &old_act, 0, sizeof( old_act );
sigemptyset( &( new_act.sa_mask ) );
new_act.sa_sigaction = handler;
new_act.sa_flags = SA_SIGINFO;
sigaction( SIGABRT, &new_act, &old_act );
if ( ( old_act.sa_sigaction != ( sigaction_handler_t ) SIG_IGN ) &&
( old_act.sa_sigaction != ( sigaction_handler_t ) SIG_DFL ) )
{
original_sigabort_handler = old_act.sa_sigaction;
}
}
这篇关于使用Java/JNI时在Linux上进行信号处理的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!