c – GDB不会立即中断程序

调试大型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.

编辑:更多细节

当gdb被冻结时,我运行了perf记录-p $(pidof gdb)大约10秒钟. perf报告返回:

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完成了,我运行了仍然只显示三个线程的信息线程(如前所述):

(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

解决方法:

gdb just shows … and hangs there for several minutes up to hours.

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

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

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

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

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

上一篇:linux yum 命令


下一篇:Ubuntu 19.10 停止支持 32 位的 x86 架构