boost :: asio не может поймать SIGINT - PullRequest
0 голосов
/ 28 сентября 2018

Моя следующая программа никогда не доходит до обработчика ().Я устанавливаю свой собственный обработчик сигналов, используя набор сигналов.

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;
}

интересно, когда я использую

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

, тогда он не завершается.

1 Ответ

0 голосов
/ 29 сентября 2018

У вас есть только один поток, обслуживающий ваш io_service, и он занят while(1);, поэтому он не может запустить обработчик сигнала.

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;
}
...