Debugging 脱离Gdb而不恢复下位机
Gdb和其他任何程序一样,都不是完美的,我时不时会遇到使当前Gdb实例无法使用的bug。在这一点上,如果我有一个调试会话,其中有很多有价值的状态,我希望能够在它上面启动一个新的Gdb会话。也就是说,分离、退出Gdb并启动一个新的Gdb实例,以便在我停止的地方重新启动 然而,当分离Gdb时,它会恢复下级,以便继续在原来的位置运行,这破坏了整个练习的重点。因此,我想知道是否有可能在这样一种状态下分离,即基本上,下级就好像它被发送了一个Debugging 脱离Gdb而不恢复下位机,debugging,gdb,Debugging,Gdb,Gdb和其他任何程序一样,都不是完美的,我时不时会遇到使当前Gdb实例无法使用的bug。在这一点上,如果我有一个调试会话,其中有很多有价值的状态,我希望能够在它上面启动一个新的Gdb会话。也就是说,分离、退出Gdb并启动一个新的Gdb实例,以便在我停止的地方重新启动 然而,当分离Gdb时,它会恢复下级,以便继续在原来的位置运行,这破坏了整个练习的重点。因此,我想知道是否有可能在这样一种状态下分离,即基本上,下级就好像它被发送了一个SIGSTOP 我曾经尝试过简单地杀死Gdb,但有趣的是,这似乎是
SIGSTOP
我曾经尝试过简单地杀死Gdb,但有趣的是,这似乎是采取了劣势。我不知道这是怎么回事
当分离Gdb时,它将恢复下位机
GDB没有,内核有(假设是Linux)
我曾经尝试过简单地杀死Gdb,但有趣的是,这似乎是采取了劣势
内核发送它SIGHUP
,这通常会杀死下级。您可以使用下方的SIG\u IGN
或简单的(gdb)呼叫信号(1,1)
来防止这种情况
在那之后,您可以分离并退出GDB,但是内核将使用SIGCONT
(参见下面的更新)恢复次进程,因此您回到了原点
然而,有一个解决办法。考虑下面的程序:
int main()
{
while (1) {
printf("."); fflush(0); sleep(1);
}
}
gdb -q ./a.out
(gdb) run
Starting program: /tmp/a.out
.....^C
Program received signal SIGINT, Interrupt.
0x00007ffff7ad5de0 in __nanosleep_nocancel () at ../sysdeps/unix/syscall-template.S:81
81 ../sysdeps/unix/syscall-template.S: No such file or directory.
我们希望程序不会在分离时跑掉,因此我们发送它SIGSTOP
:
(gdb) signal SIGSTOP
Continuing with signal SIGSTOP.
Program received signal SIGSTOP, Stopped (signal).
0x00007ffff7ad5de0 in __nanosleep_nocancel () at ../sysdeps/unix/syscall-template.S:81
81 in ../sysdeps/unix/syscall-template.S
(gdb) detach
Detaching from program: /tmp/a.out, process 25382
请注意,此时gdb已分离(但仍处于活动状态),程序未运行(已停止)
现在在另一个终端:
gdb -q -ex 'set prompt (gdb2) ' -p 25382
0x00007ffff7ad5de0 in __nanosleep_nocancel () at ../sysdeps/unix/syscall-template.S:81
81 ../sysdeps/unix/syscall-template.S: No such file or directory.
(gdb2) c
Continuing.
Program received signal SIGSTOP, Stopped (signal).
0x00007ffff7ad5de0 in __nanosleep_nocancel () at ../sysdeps/unix/syscall-template.S:81
81 in ../sysdeps/unix/syscall-template.S
(gdb2) sig 0
Continuing with no signal.
程序继续运行,在第一个终端中打印点
更新:
SIGHUP
——很有趣。但是,通过什么机制
好问题。我不知道,但这似乎是答案:
从setpgid
:
我已经验证过,如果我分离并退出GDB而不停止下级,它不会得到SIGHUP
,并继续运行而不会死亡
如果我确实发送了SIGSTOP
并安排忽略SIGHUP
,那么我会看到SIGHUP
和SIGCONT
在strace
中发送,以便与手册页完全匹配:
(gdb) detach
Detaching from program: /tmp/a.out, process 41699
在另一个窗口中:strace-p41699
。返回GDB:
(gdb) quit
strace输出:
--- stopped by SIGSTOP ---
--- SIGHUP {si_signo=SIGHUP, si_code=SI_KERNEL} ---
--- SIGCONT {si_signo=SIGCONT, si_code=SI_KERNEL} ---
restart_syscall(<... resuming interrupted call ...>) = 0
write(1, ".", 1.) = 1
...
——被SIGSTOP停止---
---SIGHUP{si_signo=SIGHUP,si_code=si_KERNEL}---
---SIGCONT{si_signo=SIGCONT,si_code=si_KERNEL}---
重新启动\u syscall()=0
写入(1,“.”,1.)=1
...
“内核发送它SIGHUP
”——很有趣。但是,通过什么机制?我在ptrace
manpage中找不到任何关于SIGHUP
被发送的信息,而且下级显然没有在自己的pty中运行。哦,很有趣。我实际上不知道流程组的功能。这很好地解释了为什么我在尝试SIGSTOP
过程时丢失了一些进程。谢谢
--- stopped by SIGSTOP ---
--- SIGHUP {si_signo=SIGHUP, si_code=SI_KERNEL} ---
--- SIGCONT {si_signo=SIGCONT, si_code=SI_KERNEL} ---
restart_syscall(<... resuming interrupted call ...>) = 0
write(1, ".", 1.) = 1
...