调试核心文件

时间:2017-02-09 08:09:14

标签: multithreading gdb parent-child core

我有一个程序,其中主线程创建了大量线程。它崩溃了,我正在调试核心文件。其中一个子线程发生崩溃。为了找到原因,我需要知道主线程是否仍然存在。有没有办法找出哪个线程是最初的?

2 个答案:

答案 0 :(得分:2)

  

有没有办法找出哪个线程是最初的?

当有100个线程时,我使用以下技术来查看它们:

(gdb) shell rm gdb.txt
(gdb) set logging on   # GDB output will go to gdb.txt
(gdb) thread apply all where

现在将gdb.txt加载到您选择的编辑器或寻呼机中,查找main等。

答案 1 :(得分:1)

作为基于 UNIX 的系统的一般方法,已接受的答案按预期工作。

在 Linux(以及选择了类似 POSIX 线程实现策略的操作系统)上,识别主线程会更加直接。通常,核心转储的文件名包含故障进程的 PID (e.g. core.<pid>),除非核心模式 (/proc/sys/kernel/core_pattern) 已更改。这样,您就可以使用 thread find <pid>:

可靠地确定主线程
$ gdb executable core.24533
[...]
(gdb) thread find 24533
Thread 7 has target id 'Thread 0x7f8ae2169740 (LWP 24533)'
(gdb) thread 7
[Switching to thread 7 (Thread 0x7f8ae2169740 (LWP 24533))]
#0  0x00007f8ae1d40017 in pthread_join (threadid=140234458433280, thread_return=0x0) at pthread_join.c:90
90      lll_wait_tid (pd->tid);
(gdb) bt
#0  0x00007f8ae1d40017 in pthread_join (threadid=140234458433280, thread_return=0x0) at pthread_join.c:90
#1  0x00007f8ae1ae40f7 in __gthread_join (__value_ptr=0x0, __threadid=<optimized out>)
    at /usr/src/debug/gcc-4.8.5-20150702/obj-x86_64-redhat-linux/x86_64-redhat-linux/libstdc++-v3/include/x86_64-redhat-linux/bits/gthr-default.h:668
#2  std::thread::join (this=this@entry=0x5595aac42990) at ../../../../../libstdc++-v3/src/c++11/thread.cc:107
#3  0x00005595a9681468 in operator() (t=..., __closure=<optimized out>) at segv.cxx:31
#4  for_each<__gnu_cxx::__normal_iterator<std::thread*, std::vector<std::thread> >, ThreadPool::wait()::__lambda1> (__last=..., __first=..., __f=...)
    at /usr/include/c++/4.8.2/bits/stl_algo.h:4417
#5  wait (this=0x7ffcac67d860) at segv.cxx:32
#6  main (argc=<optimized out>, argv=<optimized out>) at segv.cxx:75

如果文件名缺少 PID,则可以从核心转储本身中恢复。 PID 存储在注释部分 (PT_NOTE) 中。 NT_PRSTATUSNT_PRPSINFO 都包含 PID。在多个线程的情况下,NT_PRSTATUS 存在于包括主线程在内的每个单独线程中,并且顺序未指定,而 NT_PRPSINFO 仅存在一次。

Linux x86_64 的定义(pr_pid 是我们感兴趣的领域):

struct elf_prpsinfo
{
        char    pr_state;       /* numeric process state */
        char    pr_sname;       /* char for pr_state */
        char    pr_zomb;        /* zombie */
        char    pr_nice;        /* nice val */
        unsigned long pr_flag;  /* flags */
        __kernel_uid_t  pr_uid;
        __kernel_gid_t  pr_gid;
        pid_t   pr_pid, pr_ppid, pr_pgrp, pr_sid;
        /* Lots missing */
        char    pr_fname[16];   /* filename of executable */
        char    pr_psargs[ELF_PRARGSZ]; /* initial part of arg list */
};

eu-readelf -n(由elfutils提供)可用于从NT_PRPSINFO中提取PID:

$ eu-readelf -n core
[...]
  CORE                 136  PRPSINFO
    state: 2, sname: D, zomb: 0, nice: 0, flag: 0x0000000040402504
    uid: 0, gid: 0, pid: 24533, ppid: 17322, pgrp: 24533, sid: 17299
                         ^^^^^
    fname: segv, psargs: ./segv 2 
[...]