NamelessStranger
NamelessStranger

Reputation: 53

boost::asio::io_service::run does not return while having no work

From Asio documentation

The run() function blocks until all work has finished and there are no more handlers to be dispatched, or until the io_service has been stopped.

In the following snippet Asio has no work apart from debug output (which is instantly computed), but run() does not return.

#define BOOST_ASIO_ENABLE_HANDLER_TRACKING

#include <iostream>
#include <thread>

#include <boost/asio.hpp>

int main()
{
  namespace asio = boost::asio;

  asio::io_service ios;

  asio::ip::udp::endpoint ep(boost::asio::ip::udp::v4(), 9876);
  auto socket = new asio::ip::udp::socket(ios, ep);
  std::thread th([&]
  {
      ios.dispatch([]{ std::cout << "before run()" << std::endl;});
      ios.run();
      std::cout << "after run()" << std::endl;
  });

  std::this_thread::sleep_for(std::chrono::seconds(5)); // wait for io_service to launch

  socket->cancel();
  socket->close();
  delete socket; // just in case

  std::cout << "socket is closed" << std::endl;

  th.join(); // hangs here

  std::cout << "exiting..." << std::endl;
}

The output before hang is

@asio|1433598048.101578|0*1|[email protected]
@asio|1433598048.101785|>0|
before run()
socket is closed

Without socket this snippet works just fine.

I'm using Ubuntu 15.04 and I tried gcc-4.9.2, gcc-5.1, clang-3.6, boost-1.56 and boost-1.58.

Is this a bug and if so, is there any workaround, or I just misunderstand something?

UPDATE
This bug is reproducing only with following file, that must be compiled together with above snippet in other translation unit:

#include <boost/asio.hpp>

namespace asio = boost::asio;

class my_server
{
public:
  my_server(asio::io_service& ios);

private:

  asio::io_service& _ios;
  asio::ip::udp::socket _socket;
};

my_server::my_server(boost::asio::io_service &ios)
  : _ios(ios), _socket(ios, asio::ip::udp::endpoint())
{
}

I created minimal project at https://github.com/shadeware/asio-problem

Upvotes: 4

Views: 1654

Answers (1)

rhashimoto
rhashimoto

Reputation: 15841

Apparently if you choose to define BOOST_ASIO_ENABLE_HANDLER_TRACKING then you must do so in all boost::asio translation units. I don't see this mentioned in the documentation, but I did find it on the Boost mailing list.

When I add

add_definitions(-DBOOST_ASIO_ENABLE_HANDLER_TRACKING)

to your CMakeLists.txt so it is applied globally then I don't see the hang.

Upvotes: 3

Related Questions