I have a WebSocket server done with Boost.ASIO and Boost.Beast. It follows the idiomatic ASIO design: session (connection) objects own the communication socket and derive from std::enable_shared_from_this
. Async completion handlers capture a std::shared_ptr
to self keeping the object alive while there're pending operations, and the objects get destructed automatically when the chain of async ops end. The io_context
runs on a single thread, so everything is in an implicit strand.
All this is fairly simple when there's only one chain of async handlers. The session objects I have contain an additional TCP socket and a timer. Read operations are concurrently pending on 2 sockets forwarding messages back and forth, while the timer runs periodically to clean up things. To kill such an object I created a destroySession
method that calls cancel
an all resources, and eventually completion handlers get called with operation_cancelled
. When these all return without scheduling any new async op, then the object gets destructed. destroySession
calls are carefully placed at every location where a critical error happens that should result in session termination.
Question1: Is there better way to destruct such an object? With the above solution I feel like I'm back 90's where I forget a delete
somewhere and I got a leak...
Given that all destroySession
calls are there, is it still possible to leak objects? In some test envs I see 1 session object in 1000 that fails to destruct. I'm thinking of a similar scenario:
- websocket closure and timer expiry happens at the same time
- websocket completion handler gets invoked, timer handler enqueued
- websocket completion handler cancels everything
- timer expiry handler gets called (not knowing the error) reschedules the timeout
- timer cancel handler gets invoked and simply returns, object remains alive (by the timer)
Is this scenario plausible?
Question2: After calling cancel on a timer/socket can ASIO invoke an already enqueued completion handler with other status than operation_cancelled
?