Boost :: asio :: tcp :: socket Close and cancel without calling handlers

I am writing a server with boost asio library. The server handles many concurrent connections using a collection of Connection objects (the wrapper class around boost :: asio :: tcp :: socket). In the Connection class, the socket is constantly read using socket.async_read_some (...) and whenever the read handler is called with new data, socket.async_read_some () is immediately called again to get more data.

Now the server can decide to disconnect the client for some reason, so it is natural to call connection.close (), which in turn calls socket.close (), which will cause all pending async operations to be canceled. This causes the read handler (associated with the method inside the Connection class) to be called with boost :: asio :: error :: operation_aborted. And my problem: I do not want this to happen.

After socket.close (), I would like to destroy the socket and connection, and then remove its pointer from the list of active server clients. However, the read handler will not be called until the next iteration of io_service.run (), which means that I cannot immediately destroy the socket or read handler that I passed socket.async_read_some () until the handler was called with an error. Therefore, I must somehow postpone the destruction of these objects; it is annoying.

Is there a safe way to

  • Cancel pending async operations without calling the handler, so I can safely destroy the socket right after socket.close () or
  • to safely know when more handlers could potentially be called

Or do I completely disagree with this?

+6
source share
1 answer

When the async.operation operation is completed β€” either successfully or with an error β€” its completion handler is called. This is an important guarantee, and I don’t think it’s a good idea to try to β€œcrack” this behavior. The problem that you encountered in your use case is usually handled using shared_ptr (shared_from_this idiom): bind shared_ptr<Connection> for handlers does not throw another async_read when you get operation_aborted (or some other error), so when everything handlers are executed, the Connection object is destroyed with its socket.

+4
source

Source: https://habr.com/ru/post/915946/


All Articles