Boost logo

Boost :

From: JH (jupiter.hce_at_[hidden])
Date: 2019-07-17 11:03:34


On 7/16/19, Gavin Lambert via Boost <boost_at_[hidden]> wrote:
>
> Be careful of the order of operations when you have pending async actions.
>
> In particular, when you close a socket, the async read will be cancelled
> and a cancellation callback will be queued to the io_context -- but you
> must still guarantee that all of the objects involved in the callback
> for that operation (including the socket and the read buffer, plus
> anything else accessed by the completion handler) are still kept alive
> until the callback actually executes.

That seems the cause of the crash, if I terminated the socket object
after it connected to the remote server but before it transmitted any
messages, it was fine, but once it transmitted messages to the remote
server, it crashed in termination process.

> A simple trick to help ensure this (as demonstrated in several of the
> Asio examples) is to pass a shared_ptr to the container of the socket
> and read buffer to the async_read operation (eg. as a bound lambda
> argument); this will keep that object and its children alive until the
> handler is actually called.

Right, the socket is in shared_ptr, but the read buf is not, need be fixed.

> Of course, then you can't use destruction of that object to trigger the
> close in the first place, which can have consequences for the rest of
> your app. There are some ways around this, such as separating the
> "real" container of the socket/buffer from the "logical" container from
> the perspective of the rest of the app.

Did you mean if to use class destructor to trigger the close, it would
cause errors like pure virtual method called terminate called without
an active exception? Did you allude every close need be explicitly
called in functions not the destructors, especially the derived the
class?

On 7/16/19, Mathias Gaunard <mathias.gaunard_at_[hidden]> wrote:
> You need to guarantee "this" still lives when the callback runs.
>
> You probably want to capture a shared ptr of "this" rather than "this"
> here.
> enable_shared_from_this is typically used for these scenarios.

So all the callbacks need be wrapped by shared_ptr? Does that mean the
bind callback:

boost::bind(&SocketHandler::Handshake, this, boost::asio::placeholders::error)

Should be replaced by
boost::bind(&shared_ptr<SocketHandler::Handshake>, this,
boost::asio::placeholders::error)

Will it be compiled? Will try it.

Thank you all, so many tricks.

- jh


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