我该如何在gdb中切换不同的fork()进程?

12

我正在调试一个多进程应用程序,

如何在fork()出的进程之间切换?


1
顺便提一下,这似乎是此问题的完全重复。 - Chris Frederick
2
@Chris,这是不同的。我想要在不同的进程之间来回切换。 - wireshark
2个回答

20
  1. 您可以让子进程休眠,然后附加一个新的GDB实例。GDB用户手册描述了此过程如下(重点是我的):

    在大多数系统上,gdb没有特殊的支持来调试使用fork函数创建其他进程的程序。当程序fork时,gdb将继续调试父进程,而子进程将不受阻碍地运行。如果您在任何子进程执行的代码中设置了断点,则子进程将收到SIGTRAP信号(除非它捕获该信号),这会导致它终止。

    但是,如果要调试子进程,则有一种不太痛苦的解决方法。在子进程执行fork后的代码中放置一个sleep调用。如果设置了某个环境变量或某个文件存在,则仅在需要在子项上运行gdb时才休眠,以便无需发生延迟。当子进程正在睡眠时,使用ps程序获取其进程ID。然后告诉gdb(如果您还调试父进程,则为gdb的新调用)附加到子进程(请参见Attach)。从那时起,您可以像调试连接的任何其他进程一样调试子进程。

    长话短说,当您启动稍后会fork的程序时,GDB将保持与父进程的连接(尽管您可以使用set follow-fork-mode child来跟随子进程)。通过让另一个进程休眠,您可以让新的GDB实例也连接到它。

  2. 使用set detach-on-fork off来控制两个进程都在gdb的控制下。默认情况下,将像往常一样调试父进程,并暂停子进程,但是通过调用set follow-fork-mode child,您可以更改此行为(以便像通常一样调试子进程并暂停父进程)。GDB用户手册描述了此过程如下:

    gdb将保留对所有forked进程(包括嵌套forks)的控制。您可以使用info inferiors命令列出由gdb控制的forked进程,并使用inferior命令从一个fork切换到另一个fork(请参见Debugging Multiple Inferiors and Programs)。

    要退出调试其中一个forked进程,可以使用detach inferiors命令从中分离(使其独立运行),也可以使用kill inferiors命令将其杀死。请参见Debugging Multiple Inferiors and Programs


这个在gdb的开箱即用版本中不可直接使用? - wireshark
@wireshark 应该可以。您只需要运行两个 GDB 实例:一个附加到原始程序,另一个附加到子进程。通过在两个 GDB 实例之间切换(我在我的答案中已经强调了这一点),您可以“在不同的进程之间来回切换”。 - Chris Frederick
您还可以在同一GDB会话中附加和分离进程。如果您知道要连接到GDB,则“pause”/“sigsuspend”比“sleep”更好。然后,该进程将等待您发出继续信号,而且您不必在进程继续之前抢占PID并附加,这是如果您依赖于“sleep”所必须的。 - Jeremy W. Sherman
@Jeremy W. Sherman,针对此情况它无法工作:http://stackoverflow.com/questions/6301130/sigint-not-trapped-while-debugging-nginx-with-gdb - wireshark

1
显示所有进程。
(gdb) info inferiors 
  Num  Description       Executable        
  1    process 1000      /tmp/a.out 
* 2    <null>            /tmp/a.out  # current attach inferior

切换不同的进程。

(gdb) inferior 1
[Switching to inferior 1 [process 1000] (/tmp/a.out)]
[Switching to thread 1.1 (LWP 1000)]

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接