SIGABRT是否为不可阻塞信号?相关技术行为疑问求解
为什么捕获SIGABRT后程序仍会终止?
你遇到的问题核心在于**abort()函数的强制终止逻辑**,而非SIGABRT本身是不可阻塞/捕获的信号,具体原因如下:
1. abort()的标准行为
根据POSIX标准,abort()的设计目标就是无条件终止进程,不管进程是否注册了SIGABRT的自定义处理函数。当你调用abort()时:
- 它会先向进程发送SIGABRT信号;
- 即使你捕获了该信号并执行了自定义处理函数,在处理函数返回后,
abort()会重置SIGABRT的处理动作为默认(终止+核心转储),并再次发送SIGABRT; - 如果这还无法终止进程,
abort()会直接调用_exit()强制退出,确保进程一定会终止。
2. 信号阻塞的无效性
你在sigaction中设置sa_mask阻塞SIGABRT,但这对abort()无效。因为abort()的实现会临时解除对SIGABRT的阻塞状态,保证信号能被进程接收,所以你的阻塞设置被绕过了。
3. 代码现象的解释
你的程序执行流程是:
- 注册SIGABRT的处理函数,打印"Ready";
- 调用
abort(),发送SIGABRT; - 执行自定义处理函数,打印"In Handler";
- 处理函数返回后,
abort()重置SIGABRT为默认动作并再次发送,触发默认终止行为,打印"Aborted"; - 进程直接终止,永远不会执行到
printf("Done")。
如果你想让进程在捕获SIGABRT后不终止,只能在处理函数中主动调用_exit()或者使用longjmp()(注意longjmp需要保证异步信号安全),但这违背了abort()的设计初衷——它就是用来在程序出现严重错误时强制终止进程的。
你的测试代码
#include <signal.h> #include <stdlib.h> #include <stdio.h> #include <unistd.h> #include <string.h> static struct sigaction old_sa; static void my_handler(int signo) { const char x[] = "In Handler\n"; write(STDOUT_FILENO, x, strlen(x)); } int main() { struct sigaction sa; memset(&sa, 0, sizeof(sa)); sa.sa_handler = my_handler; sigemptyset(&sa.sa_mask); sigaddset(&sa.sa_mask, SIGABRT); if (0 != sigaction(SIGABRT, &sa, &old_sa)) { perror("sigaction"); exit(EXIT_FAILURE); } printf("Ready\n"); abort(); printf("Done\n"); exit(0); }
编译运行命令及输出
编译运行:
gcc ./try.c && ./a.out
输出:
Ready In Handler Aborted
内容的提问来源于stack exchange,提问作者Paul Grinberg
相关产品推荐
相关产品推荐

