I was wondering what happens when an exception is thrown inside a handler function when using boost asio's run() function on the io_context from multiple threads. My thread function which calls the run operation on the io_context looks like this:
while(!io->stopped() && *stop == false) {
try {
auto cnt = io->run();
}catch(std::exception &e) {
}
if(io->stopped()) {
break;
}
}
The number of threads is 1..N. The documentation states that any subsequent calls to run() must call restart() first but restart() must not be called when there are still any active calls to run() which I can't know because there may be still threads calling run().
What is the solution for this when there is just one io_context and many threads calling run()
CodePudding user response:
You're right that you need to catch/handle exceptions.
The solution to your conundrum is quite simple: run()
should actually not be called in a loop. This realization helps because it let's you realize that once run();
exited normally, you can always do a break;
.
More generically speaking, you could also inspect the return value of run/poll{*}
member functions: if it returns zero then the service ran out of work.
See also Should the exception thrown by boost::asio::io_service::run() be caught?
The updated documentation is (mutatis mutandis) identical https://www.boost.org/doc/libs/1_77_0/doc/html/boost_asio/reference/io_service.html#boost_asio.reference.io_service.effect_of_exceptions_thrown_from_handlers.
CodePudding user response:
A normal exit from run
requires a call to restart in order for subsequent calls to run
to not return immediately. Throwing an exception is not a normal exit so it is fine to call run
again immediately.
Your code could just be:
while(true) {
try {
auto cnt = io->run();
break;
}catch(std::exception &e) {
}
}