Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Boost.Asio: Operation Cancelled on async_read

Another one in the continuing saga of myself vs. Boost.Asio...

I have a simple asynchronous client and server that utilise async_write and async_read to communicate. The client can successfully write bytes to the socket, but the server never sees them; my read handler on the server fails with "Operation cancelled".

I'm inclined to believe that this may be a timing issue with the client writing the data after the server has tried to read it and failed, but I would have thought the data would be waiting on the socket anyway (unless the socket has been closed in the meantime).

To test this I simply re-ran the read operation in the error handler, i.e.

read_handler()
{
    if (!error) {
        /* bytes read */
    } else {
        async_read(socket, buffer, read_handler)
    }
}

But all this got me was a segfault in pthread_mutex_lock via a call to async_receive.

Could anyone point me in the direction of any relevant information (or, better yet, tell me exactly what I'm doing wrong ;) )?

UPDATE: The server and client are based around the chat server example in the Asio docs, with the client and server both running under the same process (could this be an issue? Thinking a bit more they both use the same io_service...); both asynchronous and using Boost 1.44.0. I'm working on OS X but this is reproducible on Linux, too.

UPDATE II: My hunch was correct and if the server and client are given separate io_service objects the async_read sees the bytes on the socket. This does still give a segfault in boost::asio::detail::kqueue_reactor::post_immediate_completion that seems to stem from the io_service.run(). Before I go any further, is using separate io_service objects the correct approach?

like image 696
kfb Avatar asked Oct 13 '10 10:10

kfb


1 Answers

Operation cancelled (operation_aborted error code) is sent when the socket is closed or cancelled.

Most likely your connection is somehow going out of scope.

Perhaps as it happened to me you forgot to attach the async_handlers to a shared_from_this() pointer. I.e. You should be attaching your handlers like this:

async_read(m_socket,
           boost::asio::buffer((void*)m_buffer, m_header_size),
           boost::bind(&TcpConnection::handleRead, 
           shared_from_this(),
           boost::asio::placeholders::error,
           boost::asio::placeholders::bytes_transferred));

And NOT like this:

async_read(m_socket,
           boost::asio::buffer((void*)m_buffer, m_header_size),
           boost::bind(&TcpConnection::handleRead, 
           this, //<- This will go out of scope and the socket will be closed
           boost::asio::placeholders::error,
           boost::asio::placeholders::bytes_transferred));
like image 66
Txangel Avatar answered Oct 20 '22 12:10

Txangel