简体   繁体   English

GDB不会立即中断程序

[英]GDB not interrupting program immediately

When debugging a large C application, I see strange behavior from gdb : I can always interrupt the program pressing Ctrl+C : 在调试大型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)

However, after a sufficient runtime of the program (like > 1 day), I cannot easily interrupt the program anymore. 但是,经过足够的程序运行时间(如> 1天),我不能再轻易中断程序了。 When trying to interrupt the program with Ctrl+C , gdb just shows 尝试使用Ctrl+C中断程序时, gdb只显示

^C
Program received signal SIGINT, Interrupt.

and hangs there for several minutes up to hours. 并在那里挂了几分钟到几个小时。 If it takes longer than a few minutes, I usually open another terminal and kill gdb manually to be able to continue. 如果花费的时间超过几分钟,我通常会打开另一个终端并手动终止gdb以便能够继续。

Question: Is this expected behavior from gdb ? 问题:这是gdb预期行为吗? Can I set an option to avoid this? 我可以设置一个选项以避免这种情况吗?

Further details: 更多详情:

  • The application is FTL ( https://github.com/pi-hole/FTL ) 该应用程序是FTLhttps://github.com/pi-hole/FTL
  • It is multi-threaded using pthreads 它是使用pthreads多线程
  • During the waiting time after hitting Ctrl+C , gdb is at 100% CPU. Ctrl+C后的等待时间内, gdb处于100%CPU。

Edit: Further details 编辑:更多细节

I ran perf record -p $(pidof gdb) for about 10 seconds while gdb was frozen. gdb被冻结时,我运行了perf record -p $(pidof gdb)大约10秒钟。 perf report returns: perf report返回:

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

After a few minutes, gdb finished and I ran info threads which still showed only three threads (as before): 几分钟后, 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

gdb just shows ... and hangs there for several minutes up to hours. gdb只显示...并在那里挂了几分钟到几个小时。

A guess: your program creates, but does not properly join and terminate threads. 猜测:你的程序创建,但没有正确加入和终止线程。

You can confirm or disprove this by running the program for a few hours, interrupting it with Control-C , and issuing info threads command. 您可以通过运行程序几个小时,使用Control-C中断它并发出info threads命令来确认或反驳这一点。

On Linux, threads are just processes that happen to share virtual memory and file descriptors (and controlling terminal). 在Linux上,线程只是碰巧共享虚拟内存和文件描述符(以及控制终端)的进程。 When you hit Control-C , only one of your threads receives SIGINT . 当你点击Control-C ,只有一个线程收到SIGINT

In the default all-stop mode, GDB gets notified (by the kernel) that one thread has a pending SIGINT . 在默认的all-stop模式下,GDB会通知(由内核)一个线程有一个挂起的SIGINT GDB then needs to stop all the other threads of your process, and that can take non-trivial amount of time. 然后,GDB需要停止进程的所有其他线程,这可能需要花费很多时间。

Not only that, but GDB may have to repeat this several times: while the threads were running, they may have created new threads, which now must be stopped as well. 不仅如此,GDB可能不得不重复几次:当线程运行时,它们可能已经创建了新线程,现在也必须停止。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM