boost::asio 无法捕获 SIGINT

deb*_*air 1 c++ boost boost-asio ros

我的以下程序永远不会到达 handler()。我正在使用信号集安装我自己的信号处理程序。

void handler( const boost::system::error_code& error , int signal_number )
{
  ROS_ERROR("inside signal handler");
  exit(1);
}
 int main( int argc , char** argv )
{
  ros::init(argc, argv, "name", ros::init_options::NoSigintHandler);
  boost::asio::io_service io_service;


// Construct a signal set registered for process termination.
  boost::asio::signal_set signals(io_service, SIGINT );
       // Start an asynchronous wait for one of the signals to occur.
  signals.async_wait( handler );

 boost::asio::spawn(io_service, {
    while(1);
 }
);



io_service.run();
  return 0;
}
Run Code Online (Sandbox Code Playgroud)

有趣的是,当我使用

  signals.async_wait(
      [&ioSservice](boost::system::error_code& code, int signalNo) {
        ioService.stop();
      });
Run Code Online (Sandbox Code Playgroud)

那么它不会终止。

Mil*_*nek 5

您只有一个线程为您的 提供服务io_service,并且它正忙于 ,while(1);因此无法运行信号处理程序。

An 的io_service作用类似于队列。当您async_wait处理事情时,asio 会安排将回调添加到队列中以运行其关联的io_service. 当您调用时io_service::run,调用线程将从io_service队列中拉出挂起的项目并运行它们。

在这种情况下,当您调用 时io_service.run(),队列中有一个作业:由spawn它创建的作业运行一个无限while循环。由于循环永远不会结束,因此主线程永远无法完成运行该作业。稍后,当signal_set收到 时SIGINT,它将另一个作业添加到队列中以调用handler,但它永远不会运行,因为从队列中提取作业的唯一线程正忙于无限while循环。

处理这个问题的方法是避免将长时间运行的作业放入io_service队列中和/或让多个线程为以下服务提供服务io_service

void handler(const boost::system::error_code& error, int signal_number)
{
  std::cout << "inside signal handler\n";
  exit(1);
}

int main(int argc, char** argv)
{
  boost::asio::io_service io_service;

  // You can use a work object to avoid having the io_service
  // stop when its job queue empties.
  boost::asio::io_service::work work(io_service);

  boost::asio::signal_set signals(io_service, SIGINT);
  signals.async_wait(handler);

  // Now that there's a work object keeping this io_service running
  // this call isn't needed at all.  It's just here to demonstrate
  // that it works
  boost::asio::spawn(io_service, []{
      while(1);
    }
  );

  // Start a second thread to run io_service jobs
  std::thread t([&io_service]{ io_service.run(); });

  // Also handle io_service jobs on this thread
  io_service.run();
  return 0;
}
Run Code Online (Sandbox Code Playgroud)