My following program never reaches to handler(). I am installing my own signal handler using signal set.
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;
}
interesting, when i use
signals.async_wait(
[&ioSservice](boost::system::error_code& code, int signalNo) {
ioService.stop();
});
then it does not terminate.
You only have one thread servicing your io_service
, and it's busy with the while(1);
so it can't run the signal handler.
An io_service
acts like a queue. When you async_wait
on things, asio will arrange for the callbacks to be added queued to run through their associated io_service
. When you call io_service::run
, the calling thread will pull pending items from the io_service
's queue and run them.
In this case, when you call io_service.run()
, there's on job in the queue: the one created by spawn
that runs an endless while
loop. Since the loop never ends, the main thread can never finish running that job. Later, when signal_set
receives the SIGINT
, it adds another job to the queue to call handler
, but it will never be run because the only thread pulling jobs out of the queue is busy with an endless while
loop.
The way to handle this is to avoid putting long-running jobs in your io_service
's queue and/or to have multiple threads servicing the 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;
}