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