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