On 7/16/19, Gavin Lambert via Boost
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
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_ptrSocketHandler::Handshake, this, boost::asio::placeholders::error) Will it be compiled? Will try it. Thank you all, so many tricks. - jh