调试大型C应用程序时,我发现来自gdb
的奇怪行为:
我总是可以按Ctrl+C
:
^C
Program received signal SIGINT, Interrupt.
0x76f58964 in select () at ../sysdeps/unix/syscall-template.S:81
81 in ../sysdeps/unix/syscall-template.S
(gdb)
但是,经过足够的程序运行时间(例如> 1天),我不能轻易打断程序。
尝试使用Ctrl+C
中断该计划时,gdb
只显示
^C
Program received signal SIGINT, Interrupt.
并在那里挂了几分钟到几个小时。
如果花费的时间超过几分钟,我通常会打开另一个终端并手动终止gdb
以便继续。
问题:这是gdb
的预期行为吗?我可以设置一个选项来避免这种情况吗?
进一步详情:
FTL
(https://github.com/pi-hole/FTL)pthreads
Ctrl+C
后的等待时间内,gdb
处于100%CPU。修改:更多详情
perf record -p $(pidof gdb)
冻结了gdb
时,我跑了perf report
约10秒钟。 90,82% gdb gdb [.] find_thread_ptid
9,13% gdb gdb [.] ptid_equal
0,02% gdb gdb [.] iterate_over_threads
0,01% gdb [kernel.kallsyms] [k] run_timer_softirq
0,01% gdb gdb [.] 0x0016a9a4
0,00% gdb gdb [.] 0x0015a480
0,00% gdb gdb [.] 0x0016a998
0,00% gdb gdb [.] is_exited
返回:
gdb
几分钟后,info threads
完成,我运行了(gdb) info threads
Id Target Id Frame
3 Thread 0x764b8460 (LWP 10114) "socket listener" 0x76f60260 in accept () at ../sysdeps/unix/syscall-template.S:81
2 Thread 0x76cb8460 (LWP 10113) "loganalyzer" 0x76f58964 in select () at ../sysdeps/unix/syscall-template.S:81
* 1 Thread 0x76e65000 (LWP 10098) "pihole-FTL" 0x76f58964 in select () at ../sysdeps/unix/syscall-template.S:81
,但仍然只显示了三个线程(如前所述):
{{1}}
答案 0 :(得分:0)
gdb只显示......并在那里挂了几分钟到几个小时。
猜测:你的程序创建了,但没有正确地加入和终止线程。
您可以通过运行程序几个小时,使用Control-C
中断它并发出info threads
命令来确认或反驳这一点。
在Linux上,线程只是碰巧共享虚拟内存和文件描述符(以及控制终端)的进程。当您点击Control-C
时,只有一个的线程会收到SIGINT
。
在默认的all-stop
模式下,GDB会(通过内核)通知一个线程有一个挂起的SIGINT
。然后,GDB需要停止所有进程的其他线程,这可能需要花费很多时间。
不仅如此,GDB可能需要多次重复:当线程运行时,它们可能已经创建了新线程,现在也必须停止。