program crash with boost::asio::spawn and socket::async_receive_from

本小妞迷上赌 提交于 2019-12-02 15:42:48

问题


int main() {
  boost::asio::io_service io_service;

  Worker ob1(&io_service);

  ob1.AsyncRead();
  io_service.run();

}

void Worker::AsyncRead() {
   socket.async_receive_from(buffer,endpoint, handler);
}

void handler (const boost::system::error_code& error, size_t bytes_received) {
   if(!error)
       handleData();
   AsyncRead();
}

Now this works perfectly fine. But if I use boost::Spawn() to do asyncRead() it crashes.

  void work(boost::asio::io_service* io_service) {

     auto ob1 = std::make_shared<Worker>(io_service);
  boost::asio::spawn(*io_service, [ob1](
                                      boost::asio::yield_context yield) {

      ob1->AsyncRead();

   });

  }

   int main() {
      boost::asio::io_service io_service;
       work(&io_service);

      io_service.run();

    }

The stack trace for the crash is:

PC: @           0x4e3502 boost::asio::basic_io_object<>::get_service()
*** SIGSEGV (@0x18) received by PID 25135 (TID 0x7f6bde13b7c0) from PID 24; stack trace: ***
    @     0x7f6bdd37d390 (unknown)
    @           0x4e3502 boost::asio::basic_io_object<>::get_service()
    @           0x4e3074 boost::asio::basic_datagram_socket<>::async_receive_from<>()

I want to make it work with boost::spawn(). What will happen to spawn() once my work() returns?


回答1:


For starters, your code cannot possibly compile (handler must be a non-static member function of Worker, but that means it doesn't satisfy the handler requirements for async_receive_from.

But the problem you ask about appears simpler:

 auto ob1 = std::make_shared<Worker>(io_service);

Creates a shared pointer

 boost::asio::spawn(*io_service, [ob1](
                                  boost::asio::yield_context yield) {

Posts a coro onto the service, that holds a copy of ob1 so it stays alive. So far so good.

  ob1->AsyncRead();

This does an async_recieve_from, which naturally returns immediately, the coro is done and ob1 is released. But async_receive_from is still pending on the service.

If you want to use async operations inside a coro, you have to pass the yield_context as a completion token. You didn't do that.

Your code should conceptually look like:

  void work(boost::asio::io_service* io) {

  boost::asio::spawn(*io_service, [io](boost::asio::yield_context yield) {

       udp::socket socket(*io); 
       // ... more

       udp::endpoint ep;
       char buffer[1024];
       socket.async_receive_from(buffer, ep, yield); // throws on error

   });


来源:https://stackoverflow.com/questions/52783731/program-crash-with-boostasiospawn-and-socketasync-receive-from

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!