本文介绍了使用Java/JNI时在Linux上进行信号处理的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在运行于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上进行信号处理的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-06 03:47