Boost logo

Boost :

Subject: Re: [boost] async_read SEGFAULT
From: Richard Hodges (hodges.r_at_[hidden])
Date: 2019-01-06 07:27:13


Once you initiate an async operation against a memory buffer, the contents
of that buffer are *undefined* from the moment you have called the
async_XXX function until the moment control is resumed in the handler
function you submitted.

For example, imagine an object, even one protected by a strand...

void myobject::initiate_read()
{
  // notes:
  // making completion handlers mutable allows asio to move them
internally, which is an optimisation
  // it also allows them to carry move-only objects as part of their state
  auto handler = [self = this->shared_from_this()]
                 (auto ec, auto bytes_transferred) mutable
  {
    // You are now in the the completion handler.
    // you may now read from self->mybuffer
    self->handle_read(ec, bytes_transferred);
  };

  // initiate async function.
  asio::async_read_until(mysocket,
                         mybuffer, // in this case we're using a
streambuf but the principles are the same
                         '\n', // if we used
asio::buffer(some-container) as the buffer object
                         asio::bind_executor(mystrand, //
because we're using a strand, we must bind the handler
                                             std::move(handler)); // to
the strand to ensure that no two handlers run simultaneously

  // mybuffer is now in an undefined state.
  // it is inappropriate to use it in any way from now on
  // the place to read it is in the method myobject::handle_read
}

void myobject::handle_read(system::error_code ec, std::size_t
bytes_transferred)
{
  // for composed operations like async_read_until it is possible that some
data is read *and* that we get
  // an error indicated.
  // however, for now we'll ignore that complication
  if (ec == system::error_code()) // the correct way to check for 'no
error'
  {
    // it's safe to manipulate the buffer here as there are no async
operations
    // in flight that touch it.
    std::string s;
    auto is = std::istream(&mybuffer);
    std::getline(is, s);
    do_something(s);

    // NOW re-initiate the async read
    initiate_read();
  }
  else
  {
     // do error handling here and don't reinitiate read
  }
}

On Sun, 6 Jan 2019 at 07:50, hh h via Boost <boost_at_[hidden]> wrote:

> If all async_read and async_write need a static life time buffer, do I
> need to worry about potential buffer overwritten before the buffer
> process is completed?
>
> Take an example, if a lift_time_buffer is a static buffer for
> async_read, when the socket gets the data, it fills data into the
> buffer, then the buffer is passed to higher level applications for
> processing, before the buffer process is completed, the socket
> receives more data and write the data to the buffer again since it is
> async process, that will certainly result data corruption. The same
> story could apply for async_write if one static life time buffer to
> async_write.
>
> Is that thought overstated? Or it needs a real concern?
>
> _______________________________________________
> Unsubscribe & other changes:
> http://lists.boost.org/mailman/listinfo.cgi/boost
>

-- 
Richard Hodges
hodges.r_at_[hidden]
office: +442032898513
home: +376841522
mobile: +376380212 (this will be *expensive* outside Andorra!)
skype: madmongo
facebook: hodges.r

Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk