gpt4 book ai didi

c++ - boost::asio::signal_set 不恢复以前的信号处理程序

转载 作者:塔克拉玛干 更新时间:2023-11-03 07:21:33 25 4
gpt4 key购买 nike

所以我有一个可以使用 SIGQUIT 正常关闭的守护进程。此守护进程正在运行 boost::asio::io_service。我使用 boost::asio::signal_set 来捕捉这个信号。

我遇到了一种我认为完全错误的行为。当我销毁 boost::asio::signal_set 对象时,它不会恢复该信号的先前处理程序。 SIGQUIT 的先前处理程序是空操作。因此,在 boost::asio::signal_set 被销毁后收到此信号后,我的守护程序将终止。我的猜测是因为 boost::asio::signal_set 在销毁时设置了默认处理程序,即终止程序,而不是之前的处理程序。

我认为这非常不合适。我要问的是我错了吗?也许我遗漏了什么?

最佳答案

Boost.Asio 不指定已添加到 boost::asio::signal_set 的信号的结果处理程序状态然后通过 signal_set::remove()signal_set::clear() 或销毁 signal_set 删除。特别是,未为 Signal Set Service requirements 中的任何关联操作指定后置条件。 .

快速浏览signal_set_service::add() implementation :

::sigaction(signal_number, &sa, 0)

signal_set_service::clear() implementation :

struct sigaction sa;
memset(&sa, 0, sizeof(sa));
sa.sa_handler = SIG_DFL;
::sigaction(reg->signal_number_, &sa, 0)

显示对 sigaction() 的调用不处理以前安装的处理程序,并导致在通过 signal_set_service 删除信号时注册默认处理程序操作。


由于信号可能在 Boost.Asio 将信号操作设置为默认值之后传递,但在应用程序代码能够分配其自己的处理程序之前,请考虑使用 pthread_sigmask()阻止 io_service 中的所有信号。从 signal_set 中删除信号后,通过 sigaction() 分配所需的处理程序,然后取消阻止信号。

这是一个展示这种方法的完整示例:

#include <iostream>
#include <boost/asio.hpp>

void signal_handler(int signal_number)
{
std::cout << "signal_handler(): " << signal_number << std::endl;
}

int main()
{
// Force scope to control io_service lifetime.
{
boost::asio::io_service io_service;

// Boost.Asio will register an internal handler for SIGQUIT.
boost::asio::signal_set signal_set(io_service, SIGQUIT);
signal_set.async_wait(
[](const boost::system::error_code& error,
int signal_number)
{
std::cout << "siganl_set.async_wait handler: "
<< signal_number << std::endl;

// Block SIGQUIT.
sigset_t signal_mask;
sigemptyset(&signal_mask);
sigaddset(&signal_mask, SIGQUIT);
assert(pthread_sigmask(SIG_BLOCK, &signal_mask, NULL) == 0);
});

// Send SIGQUIT to this process.
raise(SIGQUIT);
// By the time raise() returns, Boost.Asio has handled SIGQUIT with its
// own internal handler, queuing it internally. At this point, Boost.Asio
// is ready to dispatch this notification to a user signal handler
// (i.e. those provided to signal_set.async_wait()) within the
// io_service event loop.

// Prior to calling the io_service, SIGQUIT is not blocked.
io_service.run();
// The user provided handler was invoked and has blocked SIGQUIT.
}

// Send SIGQUIT to this process.
raise(SIGQUIT);
// Even though Boost.Asio has set the default handler for SIGQUIT, the
// signal is blocked, so the signal has been placed into a pending state.

// Register a custom handler for SIGQUIT.
struct sigaction sa;
sigemptyset(&sa.sa_mask);
sa.sa_handler = &signal_handler;
assert(sigaction(SIGQUIT, &sa, 0) == 0);

// Unblock SIGQUIT.
sigset_t signal_mask;
sigemptyset(&signal_mask);
sigaddset(&signal_mask, SIGQUIT);
assert(pthread_sigmask(SIG_UNBLOCK, &signal_mask, NULL) == 0);
// Upon unblocking, the pending SIGQUIT signal is delivered and handled
// by the handler registered via sigaction.

std::cout << "Fin" << std::endl;
}

及其输出:

$ ./a.out 
siganl_set.async_wait handler: 3
signal_handler(): 3
Fin

关于c++ - boost::asio::signal_set 不恢复以前的信号处理程序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25524151/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com