android - 如何捕获 SIGSEGV(段错误)并在 Android 上的 JNI 下获取堆栈跟踪?

标签 android java-native-interface signals android-ndk segmentation-fault

我要搬家 a project到新的Android Native Development Kit(即JNI)并且我想捕获SIGSEGV,如果它发生(可能还有SIGILL,SIGABRT,SIGFPE),以便呈现一个很好的崩溃报告对话框,而不是(或之前)当前的发生:进程立即意外死亡,并且操作系统可能尝试重新启动它。 (编辑: JVM/Dalvik VM 捕获信号并记录堆栈跟踪和其他有用信息;我只是想为用户提供将这些信息通过电子邮件发送给我的选项。)

情况是:我没有编写的大量 C 代码在这个应用程序中完成了大部分工作(所有游戏逻辑),虽然它在许多其他平台上经过了很好的测试,但我完全有可能,在我的 Android 端口中,会给它提供垃圾并导致 native 代码崩溃,所以我想要当前显示在 Android 日志中的崩溃转储( native 和 Java)(我猜在非 Android 情况下它会是 stderr )。我可以随意修改 C 和 Java 代码,尽管回调(传入和传出 JNI)大约有 40 个,而且很明显,小差异的奖励积分。

我听说过 J2SE 中的信号链库 libjsig.so,如果我可以在 Android 上安全地安装这样的信号处理程序,那将解决我的问题的关键部分,但我看不到这样的库安卓/达尔维克。

最佳答案

编辑:从 Jelly Bean 开始,您无法获得堆栈跟踪,因为 READ_LOGS went away . :-(

我实际上得到了一个信号处理程序,没有做任何太奇特的事情,并且已经发布了使用它的代码,你可以看到 on github (编辑:链接到历史版本;从那时起我删除了崩溃处理程序)。方法如下:

  1. 使用 sigaction() 来捕获信号并存储旧的处理程序。 ( android.c:570 )
  2. 时间过去了,发生了段错误。
  3. 在信号处理程序中,最后一次调用 JNI,然后调用旧处理程序。 ( android.c:528 )
  4. 在该 JNI 调用中,记录任何有用的调试信息,然后调用 startActivity()在标记为需要在其自己的进程中的 Activity 上。 ( SGTPuzzles.java:962 , AndroidManifest.xml:28 )
  5. 当您从 Java 中返回并调用旧处理程序时,Android 框架将连接到 debuggerd 为您记录一个不错的本地跟踪,然后该进程将终止。 ( debugger.c , debuggerd.c )
  6. 与此同时,您的崩溃处理 Activity 正在启动。真的,您应该将 PID 传递给它,以便它可以等待第 5 步完成;我不这样做。在这里您向用户道歉并询问您是否可以发送日志。如果是这样,请收集 logcat -d -v threadtime 的输出并启动一个 ACTION_SEND 并填写收件人、主题和正文。用户必须按发送。 ( CrashHandler.java , SGTPuzzles.java:462 , strings.xml:41
  7. 注意 logcat 失败或耗时超过几秒钟。我遇到了一个设备,T-Mobile Pulse/Huawei U8220,其中 logcat 立即进入 T (跟踪)状态并挂起。 ( CrashHandler.java:70 , strings.xml:51 )

在非 Android 情况下,其中一些会有所不同。您需要收集自己的本地跟踪,请参阅 this other question ,取决于你有什么样的 libc。您需要处理转储该跟踪,启动单独的崩溃处理程序进程,并以适合您平台的某些方式发送电子邮件,但我认为一般方法应该仍然有效。

关于android - 如何捕获 SIGSEGV(段错误)并在 Android 上的 JNI 下获取堆栈跟踪?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1083154/

相关文章:

java - Android 服务未接收来自 Activity 的消息

android - 行删除后 SQLite 数据获取问题?

Java/JVMTI : Usage of JavaVM-parameter in Agent_OnLoad(JavaVM, 字符*,无效)

java - JNI : passing integer array from Java to C

c - 正确使用 volatile sig_atomic_t

c - PingPong 由 1 个管道和 1 个信号 : what is scanf waiting for?

android - Activity 中的共享首选项 - android

android - JNI-SIGSEGV信号SIGSEGV : invalid address when in worker thread

c++ - SEGV_ACCERR 是什么意思?

android - Android 中的完全自定义对话框,无论设备如何,外观都相同