Boost::asio::io_service::run在没有工作时不返回

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

本文关键字:工作 返回 run io asio service Boost      更新时间:2023-10-16

来自Asio文档

run()函数阻塞,直到所有的工作完成,没有更多的处理程序被调度,或者直到io_service被停止。

在下面的代码片段中,Asio除了调试输出(立即计算)之外没有任何工作,但是run()没有返回。

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

挂起前的输出为

@asio|1433598048.101578|0*1|io_service@0x611000009f00.dispatch
@asio|1433598048.101785|>0|
before run()
socket is closed

如果没有套接字,这段代码可以正常工作。

我使用的是Ubuntu 15.04,我尝试了gcc-4.9.2, gcc-5.1, clang-3.6, boost-1.56和boost-1.58。

这是一个bug,如果是,有什么解决办法,或者我只是误解了什么?


这个错误只会在以下文件中重现,必须在其他翻译单元中与上面的代码片段一起编译:

#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())
{
}

我在https://github.com/shadeware/asio-problem创建了最小项目

显然,如果您选择定义BOOST_ASIO_ENABLE_HANDLER_TRACKING,则必须在所有boost::asio翻译单元中这样做。我在文档中没有看到这一点,但我在Boost邮件列表中找到了它。

添加

add_definitions(-DBOOST_ASIO_ENABLE_HANDLER_TRACKING)

到你的CMakeLists.txt,所以它是全局应用的,然后我没有看到挂起