C++程序无法第二次捕获SIGSEGV段错误的问题咨询
问题结论
该问题完全由代码实现错误导致,和操作系统无关,你的实现存在三处核心错误:
- 尝试捕获不可被捕获的SIGKILL信号:POSIX标准明确规定SIGKILL、SIGSTOP两个信号不能被捕获、阻塞或忽略,代码中
sigaction(SIGKILL, &act, 0);调用是完全无效的,会直接返回错误,你没有判断调用返回值所以未能发现该问题。 - 信号处理函数中调用了非异步信号安全的函数:
std::cout、exit()都不属于异步信号安全函数,在信号处理函数中调用这类函数会触发未定义行为。更严重的是你直接在信号处理函数中调用app()进入死循环,永远不会返回信号处理函数,导致信号上下文始终无法被清理。 - 错误的SIGSEGV处理逻辑:SIGSEGV是程序访问非法内存触发的同步信号,如果你在信号处理函数中没有修复引发段错误的内存问题,直接继续执行业务逻辑,当再次触发SIGSEGV时,内核会判定当前已经处于SIGSEGV信号处理流程中,直接执行默认的进程终止动作,不会再进入你注册的处理函数,这就是第二次触发段错误直接产生coredump的原因。
正确实现方案
要实现程序崩溃后自动重启,不要在程序内部的信号处理函数中做重启逻辑,推荐以下两种成熟方案:
- 使用外部监控托管:比如用systemd配置你的程序为系统服务,设置
Restart=on-failure参数,程序异常退出后会自动被systemd重启,这是生产环境最常用的稳妥方案。 - 父子进程隔离实现:主进程fork出子进程执行业务逻辑,主进程阻塞等待子进程退出状态,只要子进程是异常退出就重新fork新的子进程执行业务,不需要在业务进程内部处理任何崩溃相关信号。
内容的提问来源于stack exchange,提问作者LightSith
相关产品推荐
相关产品推荐

