C++中如何拦截系统信号_C++中signal函数处理Ctrl+C退出【系统】-C++

不能可靠拦截 Ctrl+C,因 signal() 非线程安全、行为不一致、多次触发易崩溃,且被库调用干扰;应使用 sigaction() 原子注册并配合 volatile sig_atomic_t 标志位延迟清理。

signal() 能否可靠拦截 Ctrl+C

signal() 可以注册对 SIGINT 的处理函数,从而响应 Ctrl+C,但**它不是线程安全的,且行为在不同系统上不一致(尤其是信号被多次触发时)**。POSIX 明确指出 signal() 是为兼容旧代码保留的接口,sigaction() 才是推荐方案。

常见错误现象:
– 注册后按 Ctrl+C 无反应(可能被后续库调用覆盖)
– 多次 Ctrl+C 导致程序崩溃(signal() 默认重置为 SIG_DFL)
– 在多线程环境中信号被任意线程接收,无法控制

  • 使用 signal(SIGINT, handler) 后,一旦触发一次,部分系统会自动恢复为默认行为,需手动再次调用 signal()(不推荐)
  • 若程序中用了 std::thread 或第三方库(如 Boost、Qt),它们可能内部调用 sigprocmask 或 pthread_sigmask,干扰 signal() 效果
  • SIGINT 是唯一保证由终端发送给前台进程组的信号,但仅当进程未忽略或阻塞它时才生效

用 sigaction() 正确注册 SIGINT 处理器

sigaction() 提供原子性注册、可屏蔽其他信号、支持重启被中断的系统调用等能力,是 C++ 中拦截 Ctrl+C 的实际标准做法。

关键点:
– 必须显式设置 sa_flags(例如 SA_RESTART 避免 read() 等调用被中断)
– sa_mask 可临时阻塞其他信号,防止嵌套调用(如 SIGINT 处理中又收到 SIGUSR1)
– 不要从信号处理器中调用非异步信号安全函数(如 std::cout、malloc、printf)

struct sigaction sa;
sa.sa_handler = [](int) {
    // 仅允许异步信号安全操作:写入全局 volatile 变量、_exit()、siglongjmp()
    g_should_exit = true;  // 声明为 volatile sig_atomic_t
};
sigemptyset(&sa.sa_mask);
sa.sa_flags = SA_RESTART;  // 让阻塞系统调用自动重试
sigaction(SIGINT, &sa, nullptr);

volatile sig_atomic_t 是什么,为什么不能用 bool

信号处理器可能在任意指令中间打断主流程,普通 bool 变量的读写不是原子的,编译器还可能对其做优化(比如缓存到寄存器),导致主循环永远看不到变化。

  • sig_atomic_t 是 C/C++ 标准定义的、能被信号处理器安全读写的整数类型(通常为 int)
  • 必须配合 volatile 使用,禁止编译器优化掉重复读取
  • 声明示例:volatile sig_atomic_t g_should_exit = 0;
  • 主循环中应这样检查:while (!g_should_exit) { ... },而非 while (true) + 内部 break

退出前清理资源要注意什么

信号处理器里不能调用 delete、close()、fclose()、std::mutex::unlock() 等——这些都不是异步信号安全函数。

夏夕资源网专注于CMS网站模板,主流语言整站网站源码下载,网站建设相关教程分享,好用的软件素材整合下载,提供一站式便捷自助服务。
1. 本站所有资源来源于用户上传和网络,如有侵权请邮件联系站长!
2. 分享目的仅供大家学习和交流,您必须在下载后24小时内删除!
3. 不得使用于非法商业用途,不得违反国家法律。否则后果自负!
4. 本站提供的源码、模板、插件等等其他资源,都不包含技术服务请大家谅解!
5. 如有链接无法下载、失效或广告,请联系管理员处理!
6. 本站资源售价只是赞助,收取费用仅维持本站的日常运营所需!
7. 如遇到加密压缩包,默认解压密码为"zy.lucklyus.top",如遇到无法解压的请联系管理员!
夏夕资源网-网站模板_免费源码_资源素材 » C++中如何拦截系统信号_C++中signal函数处理Ctrl+C退出【系统】-C++
在线时间:12:00 - 22:00
关注微信公众号:微信公众号
站长邮箱:[email protected]
  • 运营天数: 1392+
  • 资源总数: 47989+
  • 用户总数: 1+
  • 今日更新: 0+
  • 访问次数: 4001323+
  • 本周更新: 0+
  • 最后更新: 2026-03-16

本站指数

×
  • 运营天数: 1392+
  • 资源总数: 47989+
  • 用户总数: 1+
  • 今日更新: 0+
  • 访问次数: 4001323+
  • 本周更新: 0+
  • 最后更新: 2026-03-16