From ad25804febcd8fe7d03241e420a8dd5f297aa56b Mon Sep 17 00:00:00 2001 From: Giel van Schijndel Date: Sun, 24 Jun 2012 13:20:17 +0200 Subject: [PATCH] Cancel outstanding listen ops for RPC when shutting down Use Boost's signal2 slot tracking mechanism to cancel any (still open) listening sockets when receiving a shutdown signal. Signed-off-by: Giel van Schijndel --- src/bitcoinrpc.cpp | 57 +++++++++++++++++++++------------------------- 1 file changed, 26 insertions(+), 31 deletions(-) diff --git a/src/bitcoinrpc.cpp b/src/bitcoinrpc.cpp index 25ff6c1e5..8d78b8b00 100644 --- a/src/bitcoinrpc.cpp +++ b/src/bitcoinrpc.cpp @@ -2741,7 +2741,6 @@ static void RPCListen(boost::shared_ptr< basic_socket_acceptor* conn = new AcceptedConnectionImpl(acceptor->get_io_service(), context, fUseSSL); @@ -2768,8 +2767,10 @@ static void RPCAcceptHandler(boost::shared_ptr< basic_socket_acceptoris_open()) + RPCListen(acceptor, context, fUseSSL); AcceptedConnectionImpl* tcp_conn = dynamic_cast< AcceptedConnectionImpl* >(conn); @@ -2833,11 +2834,6 @@ void ThreadRPCServer2(void* parg) asio::io_service io_service; - // Make sure that we'll get stopped when the application shuts down - boost::signals2::scoped_connection rpc_listen_thread_stop( - uiInterface.QueueShutdown.connect(boost::bind( - &asio::io_service::stop, &io_service))); - ssl::context context(io_service, ssl::context::sslv23); if (fUseSSL) { @@ -2862,21 +2858,24 @@ void ThreadRPCServer2(void* parg) asio::ip::address bindAddress = loopback ? asio::ip::address_v6::loopback() : asio::ip::address_v6::any(); ip::tcp::endpoint endpoint(bindAddress, GetArg("-rpcport", 8332)); - std::list< boost::shared_ptr > acceptors; try { - acceptors.push_back(boost::shared_ptr(new ip::tcp::acceptor(io_service))); - acceptors.back()->open(endpoint.protocol()); - acceptors.back()->set_option(boost::asio::ip::tcp::acceptor::reuse_address(true)); + boost::shared_ptr acceptor(new ip::tcp::acceptor(io_service)); + acceptor->open(endpoint.protocol()); + acceptor->set_option(boost::asio::ip::tcp::acceptor::reuse_address(true)); // Try making the socket dual IPv6/IPv4 (if listening on the "any" address) boost::system::error_code v6_only_error; - acceptors.back()->set_option(boost::asio::ip::v6_only(loopback), v6_only_error); + acceptor->set_option(boost::asio::ip::v6_only(loopback), v6_only_error); - acceptors.back()->bind(endpoint); - acceptors.back()->listen(socket_base::max_connections); + acceptor->bind(endpoint); + acceptor->listen(socket_base::max_connections); - RPCListen(acceptors.back(), context, fUseSSL); + RPCListen(acceptor, context, fUseSSL); + // Cancel outstanding listen-requests for this acceptor when shutting down + uiInterface.QueueShutdown.connect(signals2::slot( + static_cast(&ip::tcp::acceptor::close), acceptor.get()) + .track(acceptor)); // If dual IPv6/IPv4 failed (or we're opening loopback interfaces only), open IPv4 separately if (loopback || v6_only_error) @@ -2884,13 +2883,17 @@ void ThreadRPCServer2(void* parg) bindAddress = loopback ? asio::ip::address_v4::loopback() : asio::ip::address_v4::any(); endpoint.address(bindAddress); - acceptors.push_back(boost::shared_ptr(new ip::tcp::acceptor(io_service))); - acceptors.back()->open(endpoint.protocol()); - acceptors.back()->set_option(boost::asio::ip::tcp::acceptor::reuse_address(true)); - acceptors.back()->bind(endpoint); - acceptors.back()->listen(socket_base::max_connections); - - RPCListen(acceptors.back(), context, fUseSSL); + acceptor.reset(new ip::tcp::acceptor(io_service)); + acceptor->open(endpoint.protocol()); + acceptor->set_option(boost::asio::ip::tcp::acceptor::reuse_address(true)); + acceptor->bind(endpoint); + acceptor->listen(socket_base::max_connections); + + RPCListen(acceptor, context, fUseSSL); + // Cancel outstanding listen-requests for this acceptor when shutting down + uiInterface.QueueShutdown.connect(signals2::slot( + static_cast(&ip::tcp::acceptor::close), acceptor.get()) + .track(acceptor)); } } catch(boost::system::system_error &e) @@ -2904,14 +2907,6 @@ void ThreadRPCServer2(void* parg) vnThreadsRunning[THREAD_RPCLISTENER]--; io_service.run(); vnThreadsRunning[THREAD_RPCLISTENER]++; - - // Terminate all outstanding accept-requests - BOOST_FOREACH(boost::shared_ptr& acceptor, acceptors) - { - acceptor->cancel(); - acceptor->close(); - } - acceptors.clear(); } void ThreadRPCServer3(void* parg)