c - GDB 不会立即中断程序

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

更多详情:

  • 应用程序是 FTL ( https://github.com/pi-hole/FTL )
  • 它是多线程的,使用pthreads
  • 在按下 Ctrl+C 后的等待时间内,gdb 的 CPU 使用率为 100%。

编辑:更多细节

我运行了 perf record -p $(pidof gdb) 大约 10 秒,而 gdb 被卡住了。 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

几分钟后,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.

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

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

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

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

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

关于c - GDB 不会立即中断程序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46502977/

相关文章:

c - C 中的默认命令行参数

使用核心文件检查使用的堆栈大小

Emacs gdb 没有运行

linux - 自动从一个 linux 系统连接到另一个

c++ - Tizen Construct() Button 方法失败

android - 如何使用 GDB 在 Android 上调试 Dalvik 可执行文件?

c - 如何确定同一 iOS 设备上对等 TCP 连接的 PID?

c - 如何在 Linux 中安装 curses.h 头文件(或包含它的包)?

c - C语言中如何从字符串中提取多个数字

linux - 我需要创建一个使用 cat 命令的动态文件名的脚本