【问题标题】:Getting a backtrace on Android from native threads?从原生线程获取 Android 的回溯?
【发布时间】:2014-07-17 15:03:23
【问题描述】:

我正在开发一个原本不是我自己的代码库(Parrot 的开源 ARDrone 库)。我已经删除了不必要的线程并隔离了一个特定线程的崩溃,即负责从无人机流式传输视频数据包的线程 [a Parrot ARDrone 2.0]。

我已将无人机从 TCP 视频输出更改为不同端口上的 UDP。当我加载 android 应用程序 [AR.Freeflight 2] 时,视频流畅地流了一段时间,但应用程序普遍崩溃,在非常长而复杂的视频管道中执行时出现致命的 SIGBUS。崩溃需要 20 秒到 15 分钟。

我在相关线程上设置了一个信号处理程序,可以成功捕获信号。我完成了将视频输入线程附加到 JVM 的过程,并且我能够使用缓存的全局引用来查找具有静态方法的 Java 类,该方法用于打印当前线程的调用堆栈(我已经用抛出一个新的 RuntimeException 并使用 Thread.dumpStack())。我之所以经历这个艰巨的过程是因为作为 NDK 一部分的仿生版本没有我应该能够直接从信号处理程序调用的本机 backtrace() 函数;看来,此方法已在 stackoverflow 的其他地方显示,可以很好地跟踪整个 C 调用堆栈如果您仍在 Java 生成的线程中。但是,在我的应用程序中,only 调用显示为在我的静态 void 跟踪打印函数之前发生

dalvik.system.NativeStart.run(Native Method)

因此,我不知道如何为我的 android 应用程序获取调用堆栈以找到此崩溃的真实位置,因为 Java 将在第一次 Java 调用线程之前发生的所有事情都视为“一个大 blob C"。有没有人有办法解决这个问题?

更新:我设法从信号处理程序的 void* 最终参数中提取了特定于 android 的 sigcontext 对象,这意味着我现在拥有信号发生之前的指令指针和堆栈指针。在这种情况下,有谁知道我如何调用 _Unwind_Backtrace 从那里回溯调用堆栈,而不是从信号处理程序本身展开?

【问题讨论】:

    标签: android multithreading android-ndk stack-trace


    【解决方案1】:

    当应用程序在本机代码中崩溃时,您实际上会记录回溯。崩溃后直接执行adb logcat -d > crash.log。此崩溃日志不包含任何符号,但 NDK 附带了工具 ndk-stack

    ndk-stack -sym <path> [-dump <path>]
    
       -sym  Contains full path to the root directory for symbols.
       -dump Contains full path to the file containing the crash dump.
             This is an optional parameter. If ommited, ndk-stack will
             read input data from stdin
    
    See docs/NDK-STACK.html in your NDK installation tree for more details.
    

    如果您链接的 .so 文件没有去除符号,这将提供可读的堆栈跟踪。

    【讨论】:

    • 这与我的经验直接相反。我已经在使用 android 监视器来观察崩溃的发生,当我运行 adb logcat -d > crash.log 时,我在 crash.log 中看到的日志与崩溃发生时 android 监视器中的日志完全相同.除了我自己生成的日志之外,唯一的“崩溃日志”是设备的 WindowManager 通知我它无法再为我的应用程序查找窗口的日志。也许您的建议对于由 VM 启动的线程是正确的,但从 C 代码启动的 pthreads 似乎根本没有被 JVM 跟踪。
    • 基本上,在过去的 48 小时里,我已经完成了足够多的调试工作,以 99.9% 确定我需要一个纯 C 解决方案。
    • 本机回溯不会显示在您的 IDE 中,因为它不是应用程序部分的一部分,而是系统部分的一部分。我通常做的是搜索 backtrace 这个词,因为这涉及到有趣的部分。我真的看不出你的情况会有所不同的原因。我们在应用程序中严重依赖原生组件,这就是我们获得可读跟踪的方式。
    • android 监视器不是 IDE。我没有使用 eclipse,我使用的是 /sdk/tools 中的监视器,可以直接访问 logcat,它为我提供了有关系统运行时的所有可用调试信息,而不仅仅是“应用程序部分”。我看到每个系统进程输出,在我完成自定义信号处理程序后,我看到了来自 libc 的默认信号处理程序,我看到了窗口管理器,来自系统的所有内容,来自 dalvikvm 服务的所有内容,以及当我在 vim 中搜索 crash.log 时对于“回溯”,我在多次运行的数千行日志中看到“E486:未找到模式:回溯”。
    • 线程是从 Java 和本机代码中产生的。我真的不记得是否只有 Java 产生的线程崩溃了。会很好奇,但完全有可能。无论哪种方式,抱歉我的回答对您没有帮助,但我们就是这样做的。
    猜你喜欢
    • 1970-01-01
    • 2011-12-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-09-01
    • 2011-05-16
    • 2016-12-30
    相关资源
    最近更新 更多