有 signal_set 捕获 SIGTERM 或 SIGINT 的示例。同时注册 SIGABRT 甚至 SIGSEGV 是否被认为是安全的?因为 signal_set 需要 io_context,所以我不确定当 SIGSEGV 发生时该上下文是否仍然有效。
另外,我不确定是否使用 signal_set 注册 SIGTERM 或 SIGINT,以及使用普通 std::signal 注册 SIGSEGV。该文档指出不可能多次注册信号。是否禁止在调用 signal_set 之后调用 std::signal ?
您正确地持有SEGV无法恢复的直觉。至少,程序无法恢复(最好的情况,尝试这样做将导致重复的SEGV)。
您还正确地注意到,如果您已经使用 Asio 的支持,则不应直接干预 POSIX 信号接口。
其余的都定义得很明确:
这里是强制使用 SEGV 6s 的演示:
#include <boost/asio.hpp>
namespace asio = boost::asio;
using namespace std::chrono_literals;
using std::this_thread::sleep_for;
struct Demo {
Demo(asio::any_io_executor ex, char const* name) : set(ex), name(name) {
for (int num : {SIGINT, SIGTERM, SIGUSR1, SIGUSR2, SIGHUP, SIGPIPE, SIGSEGV})
set.add(num);
wait_loop();
}
private:
asio::signal_set set;
char const* name;
using error_code = boost::system::error_code;
public:
void wait_loop() {
set.async_wait([this](error_code ec, int num) {
printf("%6s signal %s (%s)\n", name, ec.message().c_str(), ::strsignal(num));
sleep_for(200ms);
if (num != SIGTERM)
wait_loop();
});
}
};
int main() {
asio::thread_pool p;
auto ex = p.get_executor();
Demo first(ex, "first");
Demo second(ex, "second");
second.wait_loop(); // doubly await the second set for good measure
sleep_for(6s);
static void (*force_segv)() = nullptr;
force_segv();
p.join();
}
交互式现场演示: