I’m working with the Boost Beast advanced server example (available at Boost.org) and am using it as a basis for my own server. My understanding is that in this example, both the session and the listener are self-sustaining objects; they keep themselves alive by always attaching a shared_ptr of themselves to a callback handler. This design seems very elegant and practical as it appears to simplify error handling by allowing the structure to self-destruct when there are no pending asynchronous operations.
However, I’m unclear about how the entire system is shutdown. The code first calls ioc.stop() and then joins on the corresponding threads. I initially thought ioc.stop() would handle the cleanup of any pending handlers and associated shared_ptrs, but that does not seem to be the case. It seems more likely that any remaining handlers are destroyed by the final destruction of ioc itself, thereby cleaning up any remaining shared_ptrs.
In my server implementation, I’ve handled it by using a unique_ptr for the io_context and explicitly resetting it in the destructor of my server:
HTTPServer::HTTPServerImpl::~HTTPServerImpl()
{
m_ioc->stop();
for (auto& thread : m_iocThreads)
thread.join();
m_ioc.reset(); // reset the unique_ptr
}
I have a couple of questions regarding this shutdown process:
1.) Is the shutdown procedure in ~HTTPServerImpl, as adopted from the example, considered “clean,” in terms of properly closing all sockets? How exactly does this happen? Through the destructors of beast::tcp_stream and tcp::acceptor when the shared_ptrs destruct? Or should I explicitly call cancel()/close() before stop() through some weak_ptr (Is this cancel/close allowed from the main thread? Is it thread-safe?)? Are all asynchronous operations aborted during m_ioc.reset(), or are some handlers still executed (e.g. timers)?
2.) What exactly does stop() do in this context? Does it simply prevent new handlers from being added, or is there more to it than that? The docu says “abandoning unfinished operations”, what does that mean exactly? I can’t see that this will stop anything. No timers are aborted prematurely either.