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

信号处理程序陷入无限循环的原因及机制疑问

信号掩码误解与无限循环现象解析

核心误解澄清

  • 信号掩码的作用不是丢弃信号,而是暂时挂起信号的递送,直到信号掩码不再包含该信号(通常是信号处理程序执行完毕,内核自动恢复掩码)。
  • 默认情况下,当进程进入某个信号的处理程序时,内核会自动将该信号加入当前进程的信号掩码,防止处理过程中嵌套触发同类型信号,但这一屏蔽仅在处理程序运行期间有效;处理程序退出后,掩码会恢复为之前的状态,所有被挂起的信号会立即被递送。

测试代码的无限循环原因

你的代码中,两个信号处理程序互相发送对方的信号,形成了持续的挂起信号递送链:

  1. main函数中调用kill(getpid(), SIGTSTP),触发ctrlZHandler,此时内核将SIGTSTP加入进程的信号掩码。
  2. 在ctrlZHandler中发送SIGINT,触发ctrlCHandler,内核将SIGINT也加入信号掩码(此时掩码同时包含SIGTSTP和SIGINT)。
  3. 在ctrlCHandler中发送SIGTSTP,由于SIGTSTP处于当前掩码中,这个信号会被挂起,不会立即触发处理程序。
  4. ctrlCHandler执行完毕退出,内核恢复到ctrlZHandler执行时的掩码状态(仅包含SIGTSTP),继续执行ctrlZHandler的剩余代码直到退出。
  5. ctrlZHandler退出后,内核恢复main函数的原始信号掩码(不包含SIGTSTP和SIGINT),此时之前挂起的SIGTSTP会立即被递送,再次进入ctrlZHandler,重复上述流程,形成无限循环,永远无法执行main中后续的cout语句。

SIGFPE与SIGINT测试的循环现象解释

当两个信号处理程序互相发送对方信号时,逻辑和上述案例一致:

  • 进入SIGFPE处理程序时,SIGFPE被加入掩码,此时发送SIGINT会触发其处理程序,SIGINT也被加入掩码。
  • 在SIGINT处理程序中发送SIGFPE,该信号会因SIGFPE在掩码中而被挂起。
  • SIGINT处理程序退出后,恢复到SIGFPE处理程序的掩码,SIGFPE处理程序退出后恢复原始掩码,挂起的SIGFPE被递送,再次触发处理程序,如此交替循环。

你的预期偏差在于:误以为信号掩码会永久阻止同类型信号的触发,但实际上掩码只是在处理程序运行期间临时屏蔽,处理程序退出后,所有被挂起的信号都会被立即递送,从而导致循环触发。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.22 12:07:12