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

通过atexit()注册的处理函数是否仅会被调用一次?

核心问题解答

1. atexit()注册的函数是否只会调用一次?

是,C标准和POSIX标准均明确规定,atexit()注册的清理函数,在进程正常终止(exit()调用、main函数正常返回)时,每个注册的函数仅会被调用一次。只要注册过一次,不需要重复注册,正常终止流程下就会被执行一次。

2. 你观察到的现象为什么会发生?

你遇到的二次信号触发时exitFunc不执行,根本原因不是没重新注册,而是**exit()本身是不可重入函数,且你在信号处理上下文重入调用了exit()**:

  • 第一次收到SIGINT触发信号处理函数,调用exit(0),系统首先会把所有atexit注册的函数从注册列表中移除,再按注册顺序执行,此时exitFunc已经不在待调用的清理列表里了。
  • 如果exitFunc执行耗时较长,这时候再发SIGINT,信号会中断正在执行的exitFunc,再次进入信号处理函数调用exit(0),此时清理列表已经为空,自然不会再执行exitFunc。而且绝大多数C库实现中,重入调用exit()会直接触发快速终止逻辑,跳过所有剩余清理步骤。
  • 额外提醒:exit()本身不属于异步信号安全函数,在信号处理函数中直接调用属于未定义行为,本身就是不推荐的写法。

3. 正确的处理方案

你不需要重复注册atexit函数,只要调整信号处理逻辑即可:

  • 方案1:信号处理函数仅修改全局原子变量作为退出标记,主业务逻辑轮询到标记为真时,主动调用exit(),完全避免在信号处理上下文调用非安全函数。
  • 方案2:注册信号处理函数时,设置sa_mask阻塞SIGINT、SIGTERM、SIGHUP等信号,保证清理函数执行时不会被同类信号打断。

内容的提问来源于stack exchange,提问作者fgalan

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.16 15:24:07