diff options
author | Giel van Schijndel <me@mortis.eu> | 2012-06-24 13:20:17 +0200 |
---|---|---|
committer | Giel van Schijndel <me@mortis.eu> | 2012-06-24 15:12:15 +0200 |
commit | ad25804febcd8fe7d03241e420a8dd5f297aa56b (patch) | |
tree | 78951f499eb56ec6a2bcadc6c128f241847d3a5c | |
parent | 415a87ef363396fe689ec452a30d36b1752eab2e (diff) |
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 <me@mortis.eu>
-rw-r--r-- | src/bitcoinrpc.cpp | 57 |
1 files changed, 26 insertions, 31 deletions
diff --git a/src/bitcoinrpc.cpp b/src/bitcoinrpc.cpp index 25ff6c1e5f..8d78b8b00a 100644 --- a/src/bitcoinrpc.cpp +++ b/src/bitcoinrpc.cpp @@ -2741,7 +2741,6 @@ static void RPCListen(boost::shared_ptr< basic_socket_acceptor<Protocol, SocketA ssl::context& context, const bool fUseSSL) { - // Accept connection AcceptedConnectionImpl<Protocol>* conn = new AcceptedConnectionImpl<Protocol>(acceptor->get_io_service(), context, fUseSSL); @@ -2768,8 +2767,10 @@ static void RPCAcceptHandler(boost::shared_ptr< basic_socket_acceptor<Protocol, { vnThreadsRunning[THREAD_RPCLISTENER]++; - // Immediately start accepting new connections - RPCListen(acceptor, context, fUseSSL); + // Immediately start accepting new connections, except when we're canceled or our socket is closed. + if (error != error::operation_aborted + && acceptor->is_open()) + RPCListen(acceptor, context, fUseSSL); AcceptedConnectionImpl<ip::tcp>* tcp_conn = dynamic_cast< AcceptedConnectionImpl<ip::tcp>* >(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<ip::tcp::acceptor> > acceptors; try { - acceptors.push_back(boost::shared_ptr<ip::tcp::acceptor>(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<ip::tcp::acceptor> 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<void ()>( + static_cast<void (ip::tcp::acceptor::*)()>(&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<ip::tcp::acceptor>(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<void ()>( + static_cast<void (ip::tcp::acceptor::*)()>(&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<ip::tcp::acceptor>& acceptor, acceptors) - { - acceptor->cancel(); - acceptor->close(); - } - acceptors.clear(); } void ThreadRPCServer3(void* parg) |