简体   繁体   中英

(non-boost) ASIO `Operation aborted` error

I am just learning asio, this is the minimal reproducible example of an error that I have encountered. The error is Operation aborted (code 125). I have absolutely no idea as to why this happens. Thanks for any help.

#include <asio.hpp>
#include <asio/ip/tcp.hpp>
#include <iostream>
#include <memory>
class connection : public std::enable_shared_from_this<connection>
{
    asio::io_context& context;
    const char* host;
    public:
        connection(const char* host, asio::io_context& context) : context(context), host(host) 
        {}
        
        void start()
        {
            
            auto self = shared_from_this();
            
            asio::ip::tcp::resolver resolver{context};
            resolver.async_resolve(asio::ip::tcp::v4(), host, "http", [self](asio::error_code er, asio::ip::tcp::resolver::results_type endpoint){
                if(!er)
                {   
                  std::cout << endpoint->endpoint().address() << ' ' << endpoint->endpoint().port() << std::endl;
                } else {
                    throw std::runtime_error("Error resolving host: " + er.message() + std::to_string(er.value()));
                }
            });
        }
};
int main()
{
  asio::io_context context;
  std::make_shared<connection>("www.google.com", context)->start();
  context.run();
}

A fundamental property of ASIO is that I/O objects must out-live their asynchronous operations. The destructor of I/O objects cancel outstanding asynchronous operaitons.

In start() , a resolver is created and an asynchronous resolve operation is initiated. Then, immediately, the resolver is destructed, which cancels the operation.

One solution is to make the resolver a data member of connection , so that it lives long enough:

class connection : public std::enable_shared_from_this<connection>
{
    asio::io_context& context;
    const char* host;
    asio::ip::tcp::resolver resolver;

    public:
        connection(const char* host, asio::io_context& context) : context(context), host(host), resolver(context)
        {}
        
        void start()
        {
            auto self = shared_from_this();
            
            resolver.async_resolve(asio::ip::tcp::v4(), host, "http", [self](asio::error_code er, asio::ip::tcp::resolver::results_type endpoint){
                if(!er)
                {   
                  std::cout << endpoint->endpoint().address() << ' ' << endpoint->endpoint().port() << std::endl;
                } else {
                    throw std::runtime_error("Error resolving host: " + er.message() + std::to_string(er.value()));
                }
            });
        }
};

Alternatively, put resolver behind it's own shared pointer and capture the shared pointer in the handler:

class connection : public std::enable_shared_from_this<connection>
{
    asio::io_context& context;
    const char* host;

    public:
        connection(const char* host, asio::io_context& context) : context(context), host(host)
        {}
        
        void start()
        {
            auto self = shared_from_this();

            auto resolver = std::make_shared<asio::ip::tcp::resolver>(context);
            resolver->async_resolve(asio::ip::tcp::v4(), host, "http", [self, resolver](asio::error_code er, asio::ip::tcp::resolver::results_type endpoint){
                if(!er)
                {   
                  std::cout << endpoint->endpoint().address() << ' ' << endpoint->endpoint().port() << std::endl;
                } else {
                    throw std::runtime_error("Error resolving host: " + er.message() + std::to_string(er.value()));
                }
            });
        }
};

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM