boost::asio::signal_set不会恢复以前的信号处理程序
boost::asio::signal_set does not restore previous signal handlers
所以我有一个守护进程,它可以使用SIGQUIT
优雅地关闭。此守护程序正在运行boost::asio::io_service
。我用boost::asio::signal_set
来捕捉这个信号。
我遇到了一种我认为完全错误的行为。当我销毁boost::asio::signal_set
对象时,它不会恢复该信号的前一个处理程序。SIGQUIT
以前的处理程序是no-op。因此,在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::add()
实现简介:
::sigaction(signal_number, &sa, 0)
以及CCD_ 13实现:
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
- 获取日期异步信号安全吗?如果在信号处理程序中使用,它会导致死锁吗
- 如何在信号处理程序和普通函数中对全局变量进行互斥读写操作
- 有可能在信号处理程序中设置promise吗
- 在信号处理程序中捕获C++未处理的异常并恢复应用程序
- 通过安装信号处理程序关闭多线程应用程序
- 为什么我的信号处理程序只执行一次?
- GTK C++:找不到信号处理程序 您是否使用 -rdynamic 进行了编译?
- C++ 在信号处理程序后继续执行
- 没有信号处理程序的POSIX定时器的目的是什么?
- 为什么这个信号处理程序不能捕获 SIGHUP 或 SIGQUIT?
- 如何在C++中使用 std::bind 函数作为信号处理程序?
- 在 C++17 中,是否未定义使用无锁原子学保护从信号处理程序传递的数据?
- 如何将信号处理程序添加为方法
- 窗口上信号处理程序的异步安全写入函数
- 使用信号处理程序处理从 FIFO 接收的数据
- gtkmm/glade - 将信号处理程序连接到 MenuShell
- GTK+3 编译错误"找不到信号处理程序",您是否使用 -rdynamic 进行了编译?
- Linux 中的信号处理程序使用 sigaction (C++)
- 使用 enum 参数将 C++ 对象信号连接到 QML 信号处理程序
- 信号处理程序不要求使用dlopen或dlclose