【问题标题】:Signal Handling on Linux when using Java/JNI使用 Java/JNI 时 Linux 上的信号处理
【发布时间】:2017-10-09 13:28:16
【问题描述】:

我在一个在 Wind River Linux 上运行的嵌入式系统上工作。

它是 Java 和 C++ 的混合体,带有一些用于技术之间通信的 JNI。

我们已经构建了自定义错误处理,以便在出现任何意外错误时,我们会生成回溯和其他信息来帮助我们确定问题。

此错误处理始终由所有其他组件必须注册的 C++ 组件完成(以便可以安装适当的信号处理程序)。

因此,对于 Java 组件,我们使用 JNI 与 C++ 错误处理程序进行通信。

我们的测试程序使用 35 种不同的场景来测试所有不同类型的错误(内存不足、未处理的异常、访问冲突 stackoverflow 等)这是针对单个主线程案例和后台线程完成的。

除了在 JNI 主线程和后台线程中引起的 Stackoverflow 之外,所有测试都可以正常工作。

在 Linux 上,Stackoverflow 应该生成一个 SIGSEGV,并且应该调用已安装的 sigaction。但我们只是简单地终止,即处理程序没有被调用。

如果我们不生成 stackoverflow,而是直接引发 SIGSEGV(信号 11),我们的信号处理程序确实会被正确调用。

请注意,我们还在 Oracle (Java) 提供的 libjsig.so 上执行了 LD_PRELOAD,据推测这是在使用 JNI 时正确安装自定义信号处理程序所必需的(如果未完成,其他测试用例将失败)。

奇怪的是,如果我在没有 LD_PRELOAD 的情况下运行测试,信号处理程序确实会在这种情况下被调用。

寻找有关如何调试或解决此问题的想法

【问题讨论】:

  • 如果没有LD_PRELOAD,它可以工作..你这样做,它不起作用..听起来你正在加载的库有问题。
  • 处理 SIGSEGV 可能会很痛苦 :( Java 在内部使用它来处理异常。看看这里:jnicookbook.owsiak.org/recipe-No-015 但是,如果你有基于多线程的应用程序 (Java) 抛出异常,你仍然会遇到问题:(
  • 您可以查看名为:“信号链”并使用库 libjsig oracle.com/technetwork/java/javase/signals-139944.html
  • 是的,Brandon,图书馆显然有问题,这就是重点,但无论如何都想找出解决方案。
  • MKO,我们使用的是原始帖子中描述的信号链和 libjsig

标签: java c++ linux java-native-interface signals


【解决方案1】:

当我不得不编写 JNI 代码来处理 SIGSEGV et al - 我的代码必须在异常终止时清理一些文件状态 - 我发现手动链接 @ 更容易987654323@ 处理程序,根本不使用libjsig.so。 JVM 似乎总是以SIGABRT 异常终止——我会导致致命的SIGSEGV,JVM 会处理并转换为SIGABRT。我做了什么似乎并不重要。

我现在在 Oracle 文档中找不到它,但是 IBM documents JVM signal handling thus:

错误

如果 JVM 检测到无法恢复的情况,它会引发 SIGABRT

我的代码的一个版本(为了消除滚动条而缩写):

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

【讨论】:

    猜你喜欢
    • 2011-01-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-05-19
    • 1970-01-01
    • 2013-07-30
    • 1970-01-01
    相关资源
    最近更新 更多