Operation Canceled on async_resolve

1.6k views Asked by At

I have minor experience with c++ and facing some issue with boost-asio. I want to rewrite standard boost-asio async-http-client example (http://www.boost.org/doc/libs/1_58_0/doc/html/boost_asio/example/cpp03/http/client/async_client.cpp) in following way.

My goal is to have 2 classes;

  1. AsyncHttpClient(that stores host and has member function that will send async calls to specified path).
  2. AsyncHttpConnection (that takes io_service, host, path as parameters and follows the flow specified in boost-asio async-http-client example)

I have the following implementation

using boost::asio::ip::tcp;

class AsyncHttpConnection {
    public:
        AsyncHttpConnection(
            boost::asio::io_service& io_service,
            std::string host,
            std::string path) : resolver_(io_service),
                                socket_(io_service),
                                host_(host),
                                path_(path)
        {
            tcp::resolver::query query(host_, "http");
            resolver_.async_resolve(query,
                boost::bind(&AsyncHttpConnection::handle_resolve,
                    this,
                    boost::asio::placeholders::error,
                    boost::asio::placeholders::iterator));
        }

    private:
        std::string host_;
        std::string path_;
        tcp::resolver resolver_;
        tcp::socket socket_;
        boost::asio::streambuf request_;
        boost::asio::streambuf response_;

        void handle_resolve(
            const boost::system::error_code& err,
            tcp::resolver::iterator endpoint_iterator)
        {
            if (!err) {
                // code here
            } else {
                std::cout << err.message() << std::endl; // GOT "Operation Canceled" here
            }
        }

        // list of other handlers

};

class AsyncHttpClient {
    public:
        AsyncHttpClient(
            boost::asio::io_service& io_service,
            std::string host) : host_(host)
        {
            io_service_ = &io_service; // store address of io_service
        }

        void async_call(std::string path)
        {
            AsyncHttpConnection(*io_service_, host_, path);
        }

    private:
        std::string host_;
        boost::asio::io_service* io_service_; // pointer, because io_service is uncopyable; 
};

int main(int argc, char* argv[])
{
    boost::asio::io_service io_service;
    AsyncHttpClient boost(io_service, "www.boost.org");
    boost.async_call("/doc/libs/1_51_0/doc/html/boost_asio/example/http/client/async_client.cpp");
    io_service.run();
}

I got an error "Operation Canceled" in this particular way; If I instantiate AsyncHttpConnection in following way

int main(int argc, char* argv[])
{
    boost::asio::io_service io_service;
    AsyncHttpConnection(io_service, "www.boost.org", "path");
    io_service.run();
}

I got everything working perfectly, I think the issue is using pointer to io_service. How can I solve this issue, if io_service object is uncopyable?

1

There are 1 answers

3
sehe On BEST ANSWER
void async_call(std::string path) {
    AsyncHttpConnection(*io_service_, host_, path); 
}

The body constructs a temporary object of type AsyncHttpConnection. So, before the statement completes, the destructor for this type runs.

The default destructor does member-wise destruction. So it triggers the destructor tcp::resolver resolver_. The documentation for this class states that any pending asynchronous operation will be canceled on doing so.

In principle the "alternative" main has exactly the same problem (and indeed it fails with Operation canceled on my box). If it doesn't for you you're getting very fortunate timing of events.