我有Android原生C ++代码。但是,有时当我将应用程序发送到后台并返回时,它会与SIGSEGV
一起崩溃。我想使用自己的信号处理和打印堆栈跟踪来调试它,但是,当发生此错误时,我的信号处理根本不会被触发。
要JNI_OnLoad
方法,我已添加:
struct sigaction sighandler;
memset (&sighandler, '\0', 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\n", (long)siginfo->si_pid, (long)siginfo->si_uid);
old_sa[signal].sa_handler(signal);
}
但是,当应用程序从后台运行时,android_sigaction
永远不会因错误而被触发。我试图在代码中创建bug(在数组边界外编写),使用按钮按钮触发它并正确调用回调。
发生了什么事?
答案 0 :(得分:1)
假设您使用的是Android 5.0+设备,您的问题可能是由ART造成的。它暴露了自己的signal()
和sigaction()
,因此它有机会窃取信号并将其传递到其他地方。
出于调试目的,您可以尝试直接系统调用:
for(int signal : watched_signals)
{
syscall(_NR_sigaction, signal, &sighandler, &old_sa[signal]);
}
所以现在你的处理程序直接进入内核,ART不应该改变它。 当然它只适用于调试。如果你想用这个来做刺激 - 你需要开发一些能够尊重以前处理程序的逻辑。
P.S。同时检查返回值和errno
也是一个好主意。