Android - JNI / NDK - 与SIGSEV崩溃 - 未触发信号处理

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android - JNI / NDK - 与SIGSEV崩溃 - 未触发信号处理相关的知识,希望对你有一定的参考价值。

我有android原生C ++代码。但是,有时当我将应用程序发送到后台并返回时,它会与SIGSEGV崩溃。我想使用自己的信号处理和打印堆栈跟踪来调试它,但是,当发生此错误时,我的信号处理根本不会被触发。

对于JNI_OnLoad方法,我添加了:

struct sigaction sighandler;
memset (&sighandler, '', sizeof(sighandler));   
sighandler.sa_sigaction = &android_sigaction;
sighandler.sa_flags = SA_SIGINFO;

int watched_signals[] = { SIGABRT, SIGILL, SIGSEGV, SIGINT, SIGKILL };
for(int signal : watched_signals)
{
    sigaction(signal, &sighandler, &old_sa[signal]);
}

我有:

static struct sigaction old_sa[NSIG];

static void android_sigaction(int signal, siginfo_t *siginfo, void *context)
{
    MY_LOG("Sending PID: %ld, UID: %ld
", (long)siginfo->si_pid, (long)siginfo->si_uid);

    old_sa[signal].sa_handler(signal);
}

但是,当应用程序从后台运行时,android_sigaction永远不会因错误而受到攻击。我试图在代码中创建bug(在数组边界外编写),使用按钮按钮触发它并正确调用回调。到底是怎么回事?

答案

假设您使用的是Android 5.0+设备,您的问题可能是由ART造成的。它暴露了自己的signal()sigaction(),因此它有机会窃取信号并将其传递到其他地方。出于调试目的,您可以尝试直接系统调用:

for(int signal : watched_signals)
{
    syscall(_NR_sigaction, signal, &sighandler, &old_sa[signal]);
}

所以现在你的处理程序直接进入内核,ART不应该改变它。当然它只适用于调试。如果你想用这个来做刺激 - 你需要开发一些能够尊重前一个处理程序的逻辑。

附:还检查返回值和errno也是一个好主意。

以上是关于Android - JNI / NDK - 与SIGSEV崩溃 - 未触发信号处理的主要内容,如果未能解决你的问题,请参考以下文章

JNI & NDK

Android JNI/NDK开发JNI实现C/C++与Android/JAVA相互调用

Android 使用 jni Demo示例

Android 使用 jni Demo示例

Android NDK 从入门到精通

Android - JNI / NDK - 与SIGSEV崩溃 - 未触发信号处理