
Hi Rod, Rod Morison <rod@morison.biz> wrote:
I'm trying to think through how to perform a clean shutdown in this example. There could be a number of pending async_write()'s, each with their own socket and uncalled handler. There is probably also a socket waiting on the async_accept() with an an uncalled handler.
- With the work pending, io_service will need to call it's interrupt() function (from another thread) to stop processing, correct?
Actually, there are two basic approaches to clean shutdown. Interrupting the io_service::run() is one. The other is to cancel all outstanding work and let io_service::run() exit because it runs out of work. The first involves forcing io_service::run() to exit by calling io_service::interrupt(). As you say, this means that there will still be work pending. However, the io_service destructor causes all copies of user-defined handlers to be destroyed. If you follow the daytime server example of using shared_ptrs to manage your object lifetimes, these objects will all be cleaned up automatically. The second approach is to cancel the asynchronous operations by explicitly closing all the sockets and acceptor. The operations will all complete with the operation_aborted error, and provided you don't start any new async operations the io_service::run() function will exit due to lack of work. See the HTTP server program for an example of this approach.
- I can close the tcp::acceptor in tcp_server, but what about the socket that's listening on it?
If you're referring to the peer socket that is being "accepted", you don't need to do anything with it. The asynchronous accept operation is "owned" by the acceptor, so closing the acceptor is sufficient to abort the operation. No resource is assigned to the peer socket unless the accept is successful. Cheers, Chris