如何在Boost信号处理回调中调用默认处理生成崩溃转储?
解决方案
要在完成进程清理后触发系统默认的信号处理流程(生成崩溃转储并终止进程),你需要执行两个关键操作:恢复信号的默认处理程序,然后重新向当前进程发送该信号。因为Boost的signal_set会接管信号的处理逻辑,只有恢复默认处理并重新发送信号,系统才会执行原本的崩溃处理流程。
具体实现步骤
- 恢复默认信号处理:使用标准C库的
signal()函数,将捕获到的信号的处理程序重置为SIG_DFL(系统默认处理逻辑)。 - 重新发送信号:通过
raise()或kill(getpid(), signal_number)向当前进程重新发送该信号,触发系统的默认处理行为。
修改后的代码示例
#include <boost/asio/signal_set.hpp> #include <csignal> // 引入signal()和raise()函数 #include <unistd.h> // 引入getpid()(使用kill时需要) void signal_handler() { boost::thread([](){ boost::asio::io_context io_context; boost::asio::signal_set signals(io_context, SIGTERM, SIGSEGV, SIGABRT); spdlog::debug("Started waiting for signals"); signals.async_wait([](const boost::system::error_code& error, int signal_number) { if (!error) { print(std::fmt("got signal {}. teardown the process", signal_number)); teardown(); // 恢复信号的默认处理程序 signal(signal_number, SIG_DFL); // 重新发送信号,触发系统默认的崩溃转储和终止逻辑 raise(signal_number); // 也可以使用kill替代raise:kill(getpid(), signal_number); } else { print("error in getting the signal"); } }); io_context.run(); }); }
注意事项
- 核心转储配置:确保系统已开启核心转储功能(临时开启可执行
ulimit -c unlimited,永久生效需修改系统配置),否则SIGSEGV、SIGABRT这类信号不会生成崩溃转储文件。 - 清理逻辑安全:
teardown()函数需保证线程安全,避免在清理过程中引发新的异常或信号,导致流程中断。 - 信号上下文:对于SIGSEGV这类由非法内存访问触发的信号,重新发送后系统会保留崩溃时刻的上下文信息,生成完整的核心转储。
内容的提问来源于stack exchange,提问作者Zohar81
相关产品推荐
相关产品推荐

