Skip to content

Commit a6ccd6f

Browse files
committed
net: make CConnman::m_nodes_mutex non-recursive
This change includes `s/RecursiveMutex/Mutex/` and a pile of annotations to keep the compiler happy after the type change. Partially resolves: #19303
1 parent 487f4d1 commit a6ccd6f

File tree

1 file changed

+58
-38
lines changed

1 file changed

+58
-38
lines changed

src/net.h

Lines changed: 58 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1138,8 +1138,8 @@ class CConnman
11381138
bool Start(CScheduler& scheduler, const Options& options) EXCLUSIVE_LOCKS_REQUIRED(!m_total_bytes_sent_mutex, !m_added_nodes_mutex, !m_addr_fetches_mutex, !mutexMsgProc);
11391139

11401140
void StopThreads();
1141-
void StopNodes() EXCLUSIVE_LOCKS_REQUIRED(!m_reconnections_mutex);
1142-
void Stop() EXCLUSIVE_LOCKS_REQUIRED(!m_reconnections_mutex)
1141+
void StopNodes() EXCLUSIVE_LOCKS_REQUIRED(!m_nodes_mutex, !m_reconnections_mutex);
1142+
void Stop() EXCLUSIVE_LOCKS_REQUIRED(!m_nodes_mutex, !m_reconnections_mutex)
11431143
{
11441144
AssertLockNotHeld(m_reconnections_mutex);
11451145
StopThreads();
@@ -1170,20 +1170,20 @@ class CConnman
11701170
ConnectionType conn_type,
11711171
bool use_v2transport,
11721172
const std::optional<Proxy>& proxy_override = std::nullopt)
1173-
EXCLUSIVE_LOCKS_REQUIRED(!m_unused_i2p_sessions_mutex);
1173+
EXCLUSIVE_LOCKS_REQUIRED(!m_nodes_mutex, !m_unused_i2p_sessions_mutex);
11741174

1175-
bool CheckIncomingNonce(uint64_t nonce);
1175+
bool CheckIncomingNonce(uint64_t nonce) EXCLUSIVE_LOCKS_REQUIRED(!m_nodes_mutex);
11761176
void ASMapHealthCheck();
11771177

11781178
// alias for thread safety annotations only, not defined
1179-
RecursiveMutex& GetNodesMutex() const LOCK_RETURNED(m_nodes_mutex);
1179+
Mutex& GetNodesMutex() const LOCK_RETURNED(m_nodes_mutex);
11801180

1181-
bool ForNode(NodeId id, std::function<bool(CNode* pnode)> func);
1181+
bool ForNode(NodeId id, std::function<bool(CNode* pnode)> func) EXCLUSIVE_LOCKS_REQUIRED(!m_nodes_mutex);
11821182

11831183
void PushMessage(CNode* pnode, CSerializedNetMsg&& msg) EXCLUSIVE_LOCKS_REQUIRED(!m_total_bytes_sent_mutex);
11841184

11851185
using NodeFn = std::function<void(CNode*)>;
1186-
void ForEachNode(const NodeFn& func)
1186+
void ForEachNode(const NodeFn& func) EXCLUSIVE_LOCKS_REQUIRED(!m_nodes_mutex)
11871187
{
11881188
LOCK(m_nodes_mutex);
11891189
for (auto&& node : m_nodes) {
@@ -1192,7 +1192,7 @@ class CConnman
11921192
}
11931193
};
11941194

1195-
void ForEachNode(const NodeFn& func) const
1195+
void ForEachNode(const NodeFn& func) const EXCLUSIVE_LOCKS_REQUIRED(!m_nodes_mutex)
11961196
{
11971197
LOCK(m_nodes_mutex);
11981198
for (auto&& node : m_nodes) {
@@ -1238,21 +1238,22 @@ class CConnman
12381238
void StartExtraBlockRelayPeers();
12391239

12401240
// Count the number of full-relay peer we have.
1241-
int GetFullOutboundConnCount() const;
1241+
int GetFullOutboundConnCount() const EXCLUSIVE_LOCKS_REQUIRED(!m_nodes_mutex);
12421242
// Return the number of outbound peers we have in excess of our target (eg,
12431243
// if we previously called SetTryNewOutboundPeer(true), and have since set
12441244
// to false, we may have extra peers that we wish to disconnect). This may
12451245
// return a value less than (num_outbound_connections - num_outbound_slots)
12461246
// in cases where some outbound connections are not yet fully connected, or
12471247
// not yet fully disconnected.
1248-
int GetExtraFullOutboundCount() const;
1248+
int GetExtraFullOutboundCount() const EXCLUSIVE_LOCKS_REQUIRED(!m_nodes_mutex);
12491249
// Count the number of block-relay-only peers we have over our limit.
1250-
int GetExtraBlockRelayCount() const;
1250+
int GetExtraBlockRelayCount() const EXCLUSIVE_LOCKS_REQUIRED(!m_nodes_mutex);
12511251

12521252
bool AddNode(const AddedNodeParams& add) EXCLUSIVE_LOCKS_REQUIRED(!m_added_nodes_mutex);
12531253
bool RemoveAddedNode(std::string_view node) EXCLUSIVE_LOCKS_REQUIRED(!m_added_nodes_mutex);
12541254
bool AddedNodesContain(const CAddress& addr) const EXCLUSIVE_LOCKS_REQUIRED(!m_added_nodes_mutex);
1255-
std::vector<AddedNodeInfo> GetAddedNodeInfo(bool include_connected) const EXCLUSIVE_LOCKS_REQUIRED(!m_added_nodes_mutex);
1255+
std::vector<AddedNodeInfo> GetAddedNodeInfo(bool include_connected) const
1256+
EXCLUSIVE_LOCKS_REQUIRED(!m_added_nodes_mutex, !m_nodes_mutex);
12561257

12571258
/**
12581259
* Attempts to open a connection. Currently only used from tests.
@@ -1267,16 +1268,17 @@ class CConnman
12671268
* - Max total outbound connection capacity filled
12681269
* - Max connection capacity for type is filled
12691270
*/
1270-
bool AddConnection(const std::string& address, ConnectionType conn_type, bool use_v2transport) EXCLUSIVE_LOCKS_REQUIRED(!m_unused_i2p_sessions_mutex);
1271+
bool AddConnection(const std::string& address, ConnectionType conn_type, bool use_v2transport)
1272+
EXCLUSIVE_LOCKS_REQUIRED(!m_nodes_mutex, !m_unused_i2p_sessions_mutex);
12711273

1272-
size_t GetNodeCount(ConnectionDirection) const;
1274+
size_t GetNodeCount(ConnectionDirection) const EXCLUSIVE_LOCKS_REQUIRED(!m_nodes_mutex);
12731275
std::map<CNetAddr, LocalServiceInfo> getNetLocalAddresses() const;
12741276
uint32_t GetMappedAS(const CNetAddr& addr) const;
1275-
void GetNodeStats(std::vector<CNodeStats>& vstats) const;
1276-
bool DisconnectNode(std::string_view node);
1277-
bool DisconnectNode(const CSubNet& subnet);
1278-
bool DisconnectNode(const CNetAddr& addr);
1279-
bool DisconnectNode(NodeId id);
1277+
void GetNodeStats(std::vector<CNodeStats>& vstats) const EXCLUSIVE_LOCKS_REQUIRED(!m_nodes_mutex);
1278+
bool DisconnectNode(std::string_view node) EXCLUSIVE_LOCKS_REQUIRED(!m_nodes_mutex);
1279+
bool DisconnectNode(const CSubNet& subnet) EXCLUSIVE_LOCKS_REQUIRED(!m_nodes_mutex);
1280+
bool DisconnectNode(const CNetAddr& addr) EXCLUSIVE_LOCKS_REQUIRED(!m_nodes_mutex);
1281+
bool DisconnectNode(NodeId id) EXCLUSIVE_LOCKS_REQUIRED(!m_nodes_mutex);
12801282

12811283
//! Used to convey which local services we are offering peers during node
12821284
//! connection.
@@ -1340,13 +1342,27 @@ class CConnman
13401342
bool Bind(const CService& addr, unsigned int flags, NetPermissionFlags permissions);
13411343
bool InitBinds(const Options& options);
13421344

1343-
void ThreadOpenAddedConnections() EXCLUSIVE_LOCKS_REQUIRED(!m_added_nodes_mutex, !m_unused_i2p_sessions_mutex, !m_reconnections_mutex);
1345+
void ThreadOpenAddedConnections() EXCLUSIVE_LOCKS_REQUIRED(!m_added_nodes_mutex,
1346+
!m_nodes_mutex,
1347+
!m_reconnections_mutex,
1348+
!m_unused_i2p_sessions_mutex);
1349+
13441350
void AddAddrFetch(const std::string& strDest) EXCLUSIVE_LOCKS_REQUIRED(!m_addr_fetches_mutex);
1345-
void ProcessAddrFetch() EXCLUSIVE_LOCKS_REQUIRED(!m_addr_fetches_mutex, !m_unused_i2p_sessions_mutex);
1346-
void ThreadOpenConnections(std::vector<std::string> connect, std::span<const std::string> seed_nodes) EXCLUSIVE_LOCKS_REQUIRED(!m_addr_fetches_mutex, !m_added_nodes_mutex, !m_nodes_mutex, !m_unused_i2p_sessions_mutex, !m_reconnections_mutex);
1347-
void ThreadMessageHandler() EXCLUSIVE_LOCKS_REQUIRED(!mutexMsgProc);
1348-
void ThreadI2PAcceptIncoming();
1349-
void AcceptConnection(const ListenSocket& hListenSocket);
1351+
1352+
void ProcessAddrFetch() EXCLUSIVE_LOCKS_REQUIRED(!m_addr_fetches_mutex,
1353+
!m_nodes_mutex,
1354+
!m_unused_i2p_sessions_mutex);
1355+
1356+
void ThreadOpenConnections(std::vector<std::string> connect, std::span<const std::string> seed_nodes)
1357+
EXCLUSIVE_LOCKS_REQUIRED(!m_added_nodes_mutex,
1358+
!m_addr_fetches_mutex,
1359+
!m_nodes_mutex,
1360+
!m_reconnections_mutex,
1361+
!m_unused_i2p_sessions_mutex);
1362+
1363+
void ThreadMessageHandler() EXCLUSIVE_LOCKS_REQUIRED(!m_nodes_mutex, !mutexMsgProc);
1364+
void ThreadI2PAcceptIncoming() EXCLUSIVE_LOCKS_REQUIRED(!m_nodes_mutex);
1365+
void AcceptConnection(const ListenSocket& hListenSocket) EXCLUSIVE_LOCKS_REQUIRED(!m_nodes_mutex);
13501366

13511367
/**
13521368
* Create a `CNode` object from a socket that has just been accepted and add the node to
@@ -1359,10 +1375,11 @@ class CConnman
13591375
void CreateNodeFromAcceptedSocket(std::unique_ptr<Sock>&& sock,
13601376
NetPermissionFlags permission_flags,
13611377
const CService& addr_bind,
1362-
const CService& addr);
1378+
const CService& addr)
1379+
EXCLUSIVE_LOCKS_REQUIRED(!m_nodes_mutex);
13631380

13641381
void DisconnectNodes() EXCLUSIVE_LOCKS_REQUIRED(!m_reconnections_mutex, !m_nodes_mutex);
1365-
void NotifyNumConnectionsChanged();
1382+
void NotifyNumConnectionsChanged() EXCLUSIVE_LOCKS_REQUIRED(!m_nodes_mutex);
13661383
/** Return true if the peer is inactive and should be disconnected. */
13671384
bool InactivityCheck(const CNode& node) const;
13681385

@@ -1376,7 +1393,7 @@ class CConnman
13761393
/**
13771394
* Check connected and listening sockets for IO readiness and process them accordingly.
13781395
*/
1379-
void SocketHandler() EXCLUSIVE_LOCKS_REQUIRED(!m_total_bytes_sent_mutex, !mutexMsgProc);
1396+
void SocketHandler() EXCLUSIVE_LOCKS_REQUIRED(!m_nodes_mutex, !m_total_bytes_sent_mutex, !mutexMsgProc);
13801397

13811398
/**
13821399
* Do the read/write for connected sockets that are ready for IO.
@@ -1391,7 +1408,8 @@ class CConnman
13911408
* Accept incoming connections, one from each read-ready listening socket.
13921409
* @param[in] events_per_sock Sockets that are ready for IO.
13931410
*/
1394-
void SocketHandlerListening(const Sock::EventsPerSock& events_per_sock);
1411+
void SocketHandlerListening(const Sock::EventsPerSock& events_per_sock)
1412+
EXCLUSIVE_LOCKS_REQUIRED(!m_nodes_mutex);
13951413

13961414
void ThreadSocketHandler() EXCLUSIVE_LOCKS_REQUIRED(!m_total_bytes_sent_mutex, !mutexMsgProc, !m_nodes_mutex, !m_reconnections_mutex);
13971415
void ThreadDNSAddressSeed() EXCLUSIVE_LOCKS_REQUIRED(!m_addr_fetches_mutex, !m_nodes_mutex);
@@ -1405,7 +1423,7 @@ class CConnman
14051423
* @param[in] host String of the form "host[:port]", e.g. "localhost" or "localhost:8333" or "1.2.3.4:8333".
14061424
* @return true if connected to `host`.
14071425
*/
1408-
bool AlreadyConnectedToHost(std::string_view host) const;
1426+
bool AlreadyConnectedToHost(std::string_view host) const EXCLUSIVE_LOCKS_REQUIRED(!m_nodes_mutex);
14091427

14101428
/**
14111429
* Determine whether we're already connected to a given address:port.
@@ -1414,14 +1432,14 @@ class CConnman
14141432
* @param[in] addr_port Address and port to check.
14151433
* @return true if connected to addr_port.
14161434
*/
1417-
bool AlreadyConnectedToAddressPort(const CService& addr_port) const;
1435+
bool AlreadyConnectedToAddressPort(const CService& addr_port) const EXCLUSIVE_LOCKS_REQUIRED(!m_nodes_mutex);
14181436

14191437
/**
14201438
* Determine whether we're already connected to a given address.
14211439
*/
1422-
bool AlreadyConnectedToAddress(const CNetAddr& addr) const;
1440+
bool AlreadyConnectedToAddress(const CNetAddr& addr) const EXCLUSIVE_LOCKS_REQUIRED(!m_nodes_mutex);
14231441

1424-
bool AttemptToEvictConnection();
1442+
bool AttemptToEvictConnection() EXCLUSIVE_LOCKS_REQUIRED(!m_nodes_mutex);
14251443

14261444
/**
14271445
* Open a new P2P connection.
@@ -1439,7 +1457,7 @@ class CConnman
14391457
ConnectionType conn_type,
14401458
bool use_v2transport,
14411459
const std::optional<Proxy>& proxy_override)
1442-
EXCLUSIVE_LOCKS_REQUIRED(!m_unused_i2p_sessions_mutex);
1460+
EXCLUSIVE_LOCKS_REQUIRED(!m_nodes_mutex, !m_unused_i2p_sessions_mutex);
14431461

14441462
void AddWhitelistPermissionFlags(NetPermissionFlags& flags, std::optional<CNetAddr> addr, const std::vector<NetWhitelistPermissions>& ranges) const;
14451463

@@ -1465,7 +1483,7 @@ class CConnman
14651483
/**
14661484
* Return vector of current BLOCK_RELAY peers.
14671485
*/
1468-
std::vector<CAddress> GetCurrentBlockRelayOnlyConns() const;
1486+
std::vector<CAddress> GetCurrentBlockRelayOnlyConns() const EXCLUSIVE_LOCKS_REQUIRED(!m_nodes_mutex);
14691487

14701488
/**
14711489
* Search for a "preferred" network, a reachable network to which we
@@ -1477,7 +1495,7 @@ class CConnman
14771495
*
14781496
* @return bool Whether a preferred network was found.
14791497
*/
1480-
bool MaybePickPreferredNetwork(std::optional<Network>& network);
1498+
bool MaybePickPreferredNetwork(std::optional<Network>& network) EXCLUSIVE_LOCKS_REQUIRED(!m_nodes_mutex);
14811499

14821500
// Whether the node should be passed out in ForEach* callbacks
14831501
static bool NodeFullyConnected(const CNode* pnode);
@@ -1521,7 +1539,7 @@ class CConnman
15211539
mutable Mutex m_added_nodes_mutex;
15221540
std::vector<CNode*> m_nodes GUARDED_BY(m_nodes_mutex);
15231541
std::list<CNode*> m_nodes_disconnected;
1524-
mutable RecursiveMutex m_nodes_mutex;
1542+
mutable Mutex m_nodes_mutex;
15251543
std::atomic<NodeId> nLastNodeId{0};
15261544
unsigned int nPrevNodeCount{0};
15271545

@@ -1701,7 +1719,8 @@ class CConnman
17011719
std::list<ReconnectionInfo> m_reconnections GUARDED_BY(m_reconnections_mutex);
17021720

17031721
/** Attempt reconnections, if m_reconnections non-empty. */
1704-
void PerformReconnections() EXCLUSIVE_LOCKS_REQUIRED(!m_reconnections_mutex, !m_unused_i2p_sessions_mutex);
1722+
void PerformReconnections()
1723+
EXCLUSIVE_LOCKS_REQUIRED(!m_nodes_mutex, !m_reconnections_mutex, !m_unused_i2p_sessions_mutex);
17051724

17061725
/**
17071726
* Cap on the size of `m_unused_i2p_sessions`, to ensure it does not
@@ -1717,6 +1736,7 @@ class CConnman
17171736
{
17181737
public:
17191738
explicit NodesSnapshot(const CConnman& connman, bool shuffle)
1739+
EXCLUSIVE_LOCKS_REQUIRED(!connman.m_nodes_mutex)
17201740
{
17211741
{
17221742
LOCK(connman.m_nodes_mutex);

0 commit comments

Comments
 (0)