GDB不会立即中断程序

时间:2017-09-30 13:03:24

标签: c linux gdb signals i386

调试大型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的预期行为吗?我可以设置一个选项来避免这种情况吗?

进一步详情:

  • 该应用程序为FTLhttps://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}}

1 个答案:

答案 0 :(得分:0)

  

gdb只显示......并在那里挂了几分钟到几个小时。

猜测:你的程序创建了,但没有正确地加入和终止线程。

您可以通过运行程序几个小时,使用Control-C中断它并发出info threads命令来确认或反驳这一点。

在Linux上,线程只是碰巧共享虚拟内存和文件描述符(以及控制终端)的进程。当您点击Control-C时,只有一个的线程会收到SIGINT

在默认的all-stop模式下,GDB会(通过内核)通知一个线程有一个挂起的SIGINT。然后,GDB需要停止所有进程的其他线程,这可能需要花费很多时间。

不仅如此,GDB可能需要多次重复:当线程运行时,它们可能已经创建了新线程,现在也必须停止。