You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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. 代码现象的解释

你的程序执行流程是:

  1. 注册SIGABRT的处理函数,打印"Ready";
  2. 调用abort(),发送SIGABRT;
  3. 执行自定义处理函数,打印"In Handler";
  4. 处理函数返回后,abort()重置SIGABRT为默认动作并再次发送,触发默认终止行为,打印"Aborted";
  5. 进程直接终止,永远不会执行到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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.22 00:54:10