为什么在连接tracee的时候GDB可以屏蔽tracee的SIGKILL?

信号(7)手册页说, SIGKILL不能被捕获,阻塞或忽略。 但是我刚才注意到,在使用GDB连接到一个进程后,我不能再发送SIGKILL到这个进程(同样,其他的信号也不能传送)。 但是在我分离并退出GDB之后, SIGKILL像往常一样交付。

在我看来,GDB在连接时阻止了该信号(代表tracee),并在分离时解除阻塞。 但是, ptrace(2)手册页说:

在跟踪的过程中,即使信号被忽略,每次信号传递时Tracee也会停止。 ( SIGKILL是一个例外,具有其通常的效果。)

那为什么这样呢? GDB使用什么技巧?

这是一个示范的简单例子:

testing程序

#include <pthread.h> #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <signal.h> #include <errno.h> #include <string.h> /* Simple error handling functions */ #define handle_error_en(en, msg) \ do { errno = en; perror(msg); exit(EXIT_FAILURE); } while (0) struct sigaction act; void sighandler(int signum, siginfo_t *info, void *ptr) { printf("Received signal: %d\n", signum); printf("signal originate from pid[%d]\n", info->si_pid); } int main(int argc, char *argv[]) { printf("Pid of the current process: %d\n", getpid()); memset(&act, 0, sizeof(act)); act.sa_sigaction = sighandler; act.sa_flags = SA_SIGINFO; sigaction(SIGQUIT, &act, NULL); while(1) { ; } return 0; } 

如果你试图用SIGKILL杀死这个程序(例如,使用kill -KILL ${pid} ),它将会像预期的那样死亡。 如果您尝试发送SIGQUIT (即使用kill -QUIT ${pid} ),那么printf语句将按预期执行。 但是,如果您在发送信号之前将其附加到GDB,则不会发生任何事情:

 $ ##### in shell 1 ##### $ gdb (gdb) attach ${pid} (gdb) 

/ *现在gdb已成功连接到另一个shell:* /

 $ #### in shell 2 #### $ kill -QUIT ${pid} # nothing happen $ kill -KILL ${pid} # again, nothing happen! 

/ *现在gdb分离* /

 ##### in shell 1 #### (gdb) quit 

/ *进程将收到SIGKILL * /

 ##### in shell 2 #### $ Killed # the tracee receive **SIGKILL** eventually... 

仅供参考,我使用的是CentOS-6u3,而uname -r结果是2.6.32_1-16-0-0 。 我的GDB版本是: GNU gdb (GDB) Red Hat Enterprise Linux (7.2-56.el6)和我的GCC版本是: gcc (GCC) 3.4.6 20060404 (Red Hat 3.4.6-19.el6) 。 一台旧机器…

任何想法将不胜感激;-)

$ ##### in shell 1 ##### $ gdb (gdb) attach ${pid} (gdb)

问题是,一旦GDB连接到${pid} ,低级(被调试)进程不再运行 – 它被停止

直到它继续(使用(gdb) continue命令),或者它不再被跟踪( (gdb) detachquit ),内核将不会执行任何操作

如果你发出continuekill -QUIT之前或之后),你会看到:

 (gdb) c Continuing. 

kill -QUIT $pid在另一个shell中执行:

 Program received signal SIGQUIT, Quit. main (argc=1, argv=0x7ffdcc9c1518) at tc:35 35 } (gdb) c Continuing. Received signal: 3 signal originate from pid[123419] 

kill -KILL在另一个窗口中执行:

 Program terminated with signal SIGKILL, Killed. The program no longer exists. (gdb)