我们开发了一个在嵌入式MIPS系统中的Linux 3.4.11上运行的用户空间流程。该进程使用pthreads创建多个(> 10)线程。该过程具有一个SIGSEGV信号处理程序,该信号处理程序除其他外会生成一条日志消息,该消息将发送到我们的日志文件。作为此流程的一部分,它获得了一个信号量(不好,我知道...)。
在我们的测试过程中,该过程似乎挂起。我们目前无法为目标平台构建gdb,因此我编写了一个CLI工具,该工具使用ptrace通过PTRACE_PEEKUSR提取寄存器值和USER数据。
令我惊讶的是,我们所有的线程都在我们的崩溃处理程序内部,试图获取信号量。这(很明显?)指示信号量上的死锁,这意味着线程在握住它时死亡。当我挖掘堆栈时,当信号处理程序开始运行时,似乎几乎所有线程(一个线程除外)都处于阻塞调用(recv,poll,sleep)中。在MIPS上进行手动堆栈重建很痛苦,因此我们尚未完全完成。一个线程似乎在malloc调用的中间,这对我来说表明它是由于堆损坏而崩溃的。
有些事情还不清楚:
1)假设一个线程在malloc中崩溃,为什么所有其他线程都在运行SIGSEGV处理程序?据我了解,SIGSEGV信号被传递到故障线程,不是吗?这是否意味着我们的每个线程都崩溃了?
2)查看MIPS的sigcontext结构,似乎它不包含被访问的内存地址(badaddr)。还有另一个地方吗?我在任何地方都找不到它,但是对我来说似乎奇怪的是它不可用。
当然,如果有人可以提出继续进行分析的方法,将不胜感激!
答案 0 :(得分:2)
是的,假设您已正确捕获了线程状态,则很有可能所有线程依次崩溃。
siginfo_t
有一个si_addr
成员,该成员应为您提供故障的地址。内核是否填充是另一回事。
进程内崩溃处理程序将始终是不可靠的。您应该使用进程外处理程序,并将kernel.core_pattern
设置为调用它。在当前的内核中,没有必要将核心文件写入磁盘。您可以从标准输入中读取核心文件,也可以仅映射僵尸进程的进程内存(当内核调用崩溃处理程序时,该内存仍然可用)。