我有一个简单的 C 程序,当使用 gdb 调试时,它的行为不同。程序是这样的:
#include <stdio.h>
#include <signal.h>
int main() {
kill(getpid(), SIGFPE);
printf("I'm happy.\n");
return 0;
}
当自己运行时,我得到了这个非常奇怪的结果:
ezyang@javelin:~$ ./mini 我很高兴。 ezyang@javelin:~$ echo $? 0
没有错误!这并不是说信号没有被触发,它是:
ezyang@javelin:~$ strace -e 信号 ./mini 杀死(31950,SIGFPE)= 0 --- SIGFPE(浮点异常)@ 0 (0) --- 我很高兴
在 GDB 中,情况会有所不同:
ezyang@javelin:~/Dev/ghc-build-sandbox/libraries/unix/tests/libposix$ gdb ./mini GNU gdb (GDB) 7.5.91.20130417-cvs-ubuntu 版权所有 (C) 2013 Free Software Foundation, Inc. 许可 GPLv3+:GNU GPL 版本 3 或更高版本 这是免费软件:您可以自由更改和重新分发它。 在法律允许的范围内,不提供任何保证。输入“显示复制” 和“显示保修”了解详情。 此 GDB 配置为“x86_64-linux-gnu”。 有关错误报告说明,请参阅: ... 从 /srv/code/ghc-build-sandbox/libraries/unix/tests/libposix/mini 读取符号...(未找到调试符号)...完成。 (gdb) r 启动程序:/srv/code/ghc-build-sandbox/libraries/unix/tests/libposix/mini 警告:在 0x7ffff7ffa000 添加的符号文件系统提供的 DSO 中找不到可加载的部分 程序收到信号 SIGFPE,算术异常。 ../sysdeps/unix/syscall-template.S:81 处的 kill () 中的 0x00007ffff7a49317 81 ../sysdeps/unix/syscall-template.S:没有这样的文件或目录。 (gdb) c 继续。 程序以信号 SIGFPE 终止,算术异常。 该程序不再存在。
要求 GDB 不要停止没有区别
(gdb) 处理 SIGFPE nostop 信号停止打印传递到程序说明 SIGFPE 否 是 是 算术异常 (gdb) r 启动程序:/srv/code/ghc-build-sandbox/libraries/unix/tests/libposix/mini 警告:在 0x7ffff7ffa000 添加的符号文件系统提供的 DSO 中找不到可加载的部分 程序收到信号 SIGFPE,算术异常。 程序以信号 SIGFPE 终止,算术异常。 该程序不再存在。
这是怎么回事?!一方面,为什么 SIGFPE 不杀死程序?第二件事,为什么 GDB 的行为不同?
更新。一种想法是子进程正在继承父进程的信号掩码。 然而,从这个成绩单中可以看出,情况显然不是这样: 这个分析是不正确的,见下文。
ezyang@javelin:~$ 陷阱 - SIGFPE ezyang@javelin:~$ ./mini 我很高兴。
更新 2。我的一个朋友指出,陷阱只报告由 shell 本身设置的信号,而不是任何父进程设置的信号。所以我们追踪了所有父母的忽略掩码,你瞧,rxvt-unicode 屏蔽了 SIGFPE。一位朋友证实,当他使用 rxvt-unicode 运行可执行文件时,他可以重现。