我有一个程序,其中主线程创建了大量线程。它崩溃了,我正在调试核心文件。其中一个子线程发生崩溃。为了找到原因,我需要知道主线程是否仍然存在。有没有办法找出哪个线程是最初的?
答案 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_PRSTATUS
和 NT_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
[...]