Lock before stopping when it is necessary to notify other threads (#2608)
This prevents having all threads waiting and the system freezing. Mostly important for tests, especially with sanitizers, but could happen on stopping the node normally. Portmapping requires an atomic bool, and the database queue doesn't after this change. Other small related bootstrap changes included in this PR per Serg's suggestion.
This commit is contained in:
		
					parent
					
						
							
								81d92057d5
							
						
					
				
			
			
				commit
				
					
						78d12342ba
					
				
			
		
					 7 changed files with 33 additions and 20 deletions
				
			
		| 
						 | 
					@ -202,9 +202,11 @@ bool nano::bootstrap_attempt_legacy::consume_future (std::future<bool> & future_
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void nano::bootstrap_attempt_legacy::stop ()
 | 
					void nano::bootstrap_attempt_legacy::stop ()
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	stopped = true;
 | 
					 | 
				
			||||||
	condition.notify_all ();
 | 
					 | 
				
			||||||
	nano::unique_lock<std::mutex> lock (mutex);
 | 
						nano::unique_lock<std::mutex> lock (mutex);
 | 
				
			||||||
 | 
						stopped = true;
 | 
				
			||||||
 | 
						lock.unlock ();
 | 
				
			||||||
 | 
						condition.notify_all ();
 | 
				
			||||||
 | 
						lock.lock ();
 | 
				
			||||||
	if (auto i = frontiers.lock ())
 | 
						if (auto i = frontiers.lock ())
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		try
 | 
							try
 | 
				
			||||||
| 
						 | 
					@ -478,7 +480,7 @@ bool nano::bootstrap_attempt_legacy::request_frontier (nano::unique_lock<std::mu
 | 
				
			||||||
	lock_a.unlock ();
 | 
						lock_a.unlock ();
 | 
				
			||||||
	auto connection_l (node->bootstrap_initiator.connections->connection (shared_from_this (), first_attempt));
 | 
						auto connection_l (node->bootstrap_initiator.connections->connection (shared_from_this (), first_attempt));
 | 
				
			||||||
	lock_a.lock ();
 | 
						lock_a.lock ();
 | 
				
			||||||
	if (connection_l)
 | 
						if (connection_l && !stopped)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		endpoint_frontier_request = connection_l->channel->get_tcp_endpoint ();
 | 
							endpoint_frontier_request = connection_l->channel->get_tcp_endpoint ();
 | 
				
			||||||
		std::future<bool> future;
 | 
							std::future<bool> future;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -76,7 +76,8 @@ std::shared_ptr<nano::bootstrap_client> nano::bootstrap_connections::connection
 | 
				
			||||||
	if (result == nullptr && connections_count == 0 && new_connections_empty && attempt_a != nullptr)
 | 
						if (result == nullptr && connections_count == 0 && new_connections_empty && attempt_a != nullptr)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		node.logger.try_log (boost::str (boost::format ("Bootstrap attempt stopped because there are no peers")));
 | 
							node.logger.try_log (boost::str (boost::format ("Bootstrap attempt stopped because there are no peers")));
 | 
				
			||||||
		attempt_a->stopped = true;
 | 
							lock.unlock ();
 | 
				
			||||||
 | 
							attempt_a->stop ();
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return result;
 | 
						return result;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -440,6 +441,7 @@ void nano::bootstrap_connections::requeue_pull (nano::pull_info const & pull_a,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void nano::bootstrap_connections::clear_pulls (uint64_t bootstrap_id_a)
 | 
					void nano::bootstrap_connections::clear_pulls (uint64_t bootstrap_id_a)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
		nano::lock_guard<std::mutex> lock (mutex);
 | 
							nano::lock_guard<std::mutex> lock (mutex);
 | 
				
			||||||
		auto i (pulls.begin ());
 | 
							auto i (pulls.begin ());
 | 
				
			||||||
		while (i != pulls.end ())
 | 
							while (i != pulls.end ())
 | 
				
			||||||
| 
						 | 
					@ -453,6 +455,8 @@ void nano::bootstrap_connections::clear_pulls (uint64_t bootstrap_id_a)
 | 
				
			||||||
				++i;
 | 
									++i;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						condition.notify_all ();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void nano::bootstrap_connections::run ()
 | 
					void nano::bootstrap_connections::run ()
 | 
				
			||||||
| 
						 | 
					@ -477,9 +481,11 @@ void nano::bootstrap_connections::run ()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void nano::bootstrap_connections::stop ()
 | 
					void nano::bootstrap_connections::stop ()
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
						nano::unique_lock<std::mutex> lock (mutex);
 | 
				
			||||||
	stopped = true;
 | 
						stopped = true;
 | 
				
			||||||
 | 
						lock.unlock ();
 | 
				
			||||||
	condition.notify_all ();
 | 
						condition.notify_all ();
 | 
				
			||||||
	nano::lock_guard<std::mutex> lock (mutex);
 | 
						lock.lock ();
 | 
				
			||||||
	for (auto i : clients)
 | 
						for (auto i : clients)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		if (auto client = i.lock ())
 | 
							if (auto client = i.lock ())
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -519,7 +519,7 @@ void nano::bootstrap_attempt_wallet::request_pending (nano::unique_lock<std::mut
 | 
				
			||||||
	lock_a.unlock ();
 | 
						lock_a.unlock ();
 | 
				
			||||||
	auto connection_l (node->bootstrap_initiator.connections->connection (shared_from_this ()));
 | 
						auto connection_l (node->bootstrap_initiator.connections->connection (shared_from_this ()));
 | 
				
			||||||
	lock_a.lock ();
 | 
						lock_a.lock ();
 | 
				
			||||||
	if (connection_l)
 | 
						if (connection_l && !stopped)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		auto account (wallet_accounts.front ());
 | 
							auto account (wallet_accounts.front ());
 | 
				
			||||||
		wallet_accounts.pop_front ();
 | 
							wallet_accounts.pop_front ();
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -34,7 +34,10 @@ nano::confirmation_height_processor::~confirmation_height_processor ()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void nano::confirmation_height_processor::stop ()
 | 
					void nano::confirmation_height_processor::stop ()
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							nano::lock_guard<std::mutex> guard (mutex);
 | 
				
			||||||
		stopped = true;
 | 
							stopped = true;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
	condition.notify_one ();
 | 
						condition.notify_one ();
 | 
				
			||||||
	if (thread.joinable ())
 | 
						if (thread.joinable ())
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -59,7 +59,7 @@ private:
 | 
				
			||||||
	boost::asio::ip::address_v4 address;
 | 
						boost::asio::ip::address_v4 address;
 | 
				
			||||||
	std::array<mapping_protocol, 2> protocols;
 | 
						std::array<mapping_protocol, 2> protocols;
 | 
				
			||||||
	uint64_t check_count{ 0 };
 | 
						uint64_t check_count{ 0 };
 | 
				
			||||||
	bool on{ false };
 | 
						std::atomic<bool> on{ false };
 | 
				
			||||||
	std::mutex mutex;
 | 
						std::mutex mutex;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -77,6 +77,9 @@ nano::write_guard nano::write_database_queue::pop ()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void nano::write_database_queue::stop ()
 | 
					void nano::write_database_queue::stop ()
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							nano::lock_guard<std::mutex> guard (mutex);
 | 
				
			||||||
		stopped = true;
 | 
							stopped = true;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
	cv.notify_all ();
 | 
						cv.notify_all ();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2,7 +2,6 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <nano/lib/locks.hpp>
 | 
					#include <nano/lib/locks.hpp>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <atomic>
 | 
					 | 
				
			||||||
#include <condition_variable>
 | 
					#include <condition_variable>
 | 
				
			||||||
#include <deque>
 | 
					#include <deque>
 | 
				
			||||||
#include <functional>
 | 
					#include <functional>
 | 
				
			||||||
| 
						 | 
					@ -53,6 +52,6 @@ private:
 | 
				
			||||||
	std::mutex mutex;
 | 
						std::mutex mutex;
 | 
				
			||||||
	nano::condition_variable cv;
 | 
						nano::condition_variable cv;
 | 
				
			||||||
	std::function<void()> guard_finish_callback;
 | 
						std::function<void()> guard_finish_callback;
 | 
				
			||||||
	std::atomic<bool> stopped{ false };
 | 
						bool stopped{ false };
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue