Search code examples
c++boostsystemasio

Boost ASIO system error 995: The I/O operation has been aborted


I am trying to write a simple server that allows multiple clients to connect. When I run my program, I get the following error as output:

[3730] Press [return] to exit.
Listening on: 127.0.0.1:7777
[5d0] Thread Start
Error: system:995 The I/O operation has been aborted because of either a 
thread exit or an application request

I think this is because my Client object is falling out of scope, but I'm not entirely sure if this is actually the problem or if there's something else wrong with my code.

ClientNetwork::ClientNetwork(asio::io_service& ios, const asio::ip::tcp::endpoint& edp) : mIOService(ios), mAcceptor(ios, edp)
{
    /*mAcceptor.open(edp.protocol());
    mAcceptor.set_option(boost::asio::ip::tcp::acceptor::reuse_address(false));*/
    listen();
}
ClientNetwork::~ClientNetwork()
{
    boost::system::error_code ec;
    mAcceptor.close(ec);

    mConnectionThreads.join_all();
    mClients.clear();
    std::cout << "KILLING NETWORK" << std::endl;
}
void ClientNetwork::listen()
{
    mConnectionThreads.create_thread(boost::bind(&ClientNetwork::connectionThread, this));
    Client* c = new Client(mIOService);
    mAcceptor.listen(boost::asio::socket_base::max_connections);
    mAcceptor.async_accept(*c->getSocket(), boost::bind(&ClientNetwork::handleAccept, this, _1, c));

}

void ClientNetwork::handleAccept(const boost::system::error_code& error, Client* client)
{

    if (!error)
    {
        mClients.push_back(client);
        mConnectionThreads.create_thread(boost::bind(&ClientNetwork::connectionThread, this));
        std::cout << mConnectionThreads.size() << std::endl;
    }
    else
    {
        std::cout << "Error: " << error << " " << error.message() << std::endl;
    }
}

This is my main (not sure it's entirely helpful but felt it would be good to include:

int main(int argc, char * argv[])
{
    boost::shared_ptr< boost::asio::io_service > io_service(
        new boost::asio::io_service
    );
    boost::shared_ptr< boost::asio::io_service::work > work(
        new boost::asio::io_service::work(*io_service)
    );
    boost::shared_ptr< boost::asio::io_service::strand > strand(
        new boost::asio::io_service::strand(*io_service)
    );
    global_stream_lock.lock();
    std::cout << "[" << boost::this_thread::get_id()
        << "] Press [return] to exit." << std::endl;
    global_stream_lock.unlock();

    /*boost::thread_group worker_threads;
    for (int x = 0; x < 2; ++x)
    {
        worker_threads.create_thread(boost::bind(&WorkerThread, io_service));
    }*/

    /*boost::shared_ptr< boost::asio::ip::tcp::acceptor > acceptor(
        new boost::asio::ip::tcp::acceptor(*io_service)
    );
    boost::shared_ptr< boost::asio::ip::tcp::socket > sock(
        new boost::asio::ip::tcp::socket(*io_service)
    );*/

    try
    {
        boost::asio::ip::tcp::resolver resolver(*io_service);
        boost::asio::ip::tcp::resolver::query query(
            "127.0.0.1",
            boost::lexical_cast< std::string >(7777)
        );
        boost::asio::ip::tcp::endpoint endpoint = *resolver.resolve(query);



        ClientNetwork clientNet(*io_service, endpoint);

        global_stream_lock.lock();
        std::cout << "Listening on: " << endpoint << std::endl;
        global_stream_lock.unlock();
    }
    catch (std::exception & ex)
    {
        global_stream_lock.lock();
        std::cout << "[" << boost::this_thread::get_id()
            << "] Exception: " << ex.what() << std::endl;
        global_stream_lock.unlock();
    }

    std::cin.get();

    //worker_threads.join_all();

    return 0;
}

Solution

  • After creating ClientNetwork object and when first an asynchronous operation was started you should run io_service::run method to process handlers in events loop then your program runs until there is at least one asynchronous operation to be executed.

    At the end of try scope put io_service->run():

        ClientNetwork clientNet(*io_service, endpoint);
    
        global_stream_lock.lock();
        std::cout << "Listening on: " << endpoint << std::endl;
        global_stream_lock.unlock();
        io_service->run();
    

    Without this the destructor of ClientNetwork class is called and mAcceptor is closed with printing this error message

    void ClientNetwork::handleAccept (...) {
      ...
      std::cout << "Error: " << error << " " << error.message() << std::endl;
    }