signal(7)页面上说,SIGKILL不能被捕获、阻塞或忽略。但是我刚刚观察到,在使用GDB附加到进程后,我无法再向该进程发送SIGKILL(同样,其他信号也不能传递)。但是在我解除附加并退出GDB后,SIGKILL会像往常一样被发送。
在我看来,当GDB附加时,它代表追踪者阻止了该信号(代表被追踪者),并在解除附加后启用了该信号。但是,ptrace(2)中说道:
以下是一个简单的演示例子:
/* 现在gdb已经成功附加,打开另一个shell: */
在我看来,当GDB附加时,它代表追踪者阻止了该信号(代表被追踪者),并在解除附加后启用了该信号。但是,ptrace(2)中说道:
那么为什么会这样呢?GDB使用了哪些技巧?在被跟踪时,即使忽略了信号,被跟踪者也会停止每次发送信号。 (一个例外是SIGKILL,它具有其通常的效果。)
以下是一个简单的演示例子:
#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)
。这是一台旧机器...
任何想法将不胜感激 ;-)