mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-02-10 10:52:31 -05:00
net: dedup and RAII-fy the creation of a copy of CConnman::vNodes
The following pattern was duplicated in CConnman: ```cpp lock create a copy of vNodes, add a reference to each one unlock ... use the copy ... lock release each node from the copy unlock ``` Put that code in a RAII helper that reduces it to: ```cpp create snapshot "snap" ... use the copy ... // release happens when "snap" goes out of scope ```
This commit is contained in:
parent
b9cf505bdf
commit
75e8bf55f5
2 changed files with 61 additions and 50 deletions
38
src/net.cpp
38
src/net.cpp
|
@ -1513,18 +1513,12 @@ void CConnman::SocketHandler()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const NodesSnapshot snap{*this, /*shuffle=*/false};
|
||||||
|
|
||||||
//
|
//
|
||||||
// Service each socket
|
// Service each socket
|
||||||
//
|
//
|
||||||
std::vector<CNode*> vNodesCopy;
|
for (CNode* pnode : snap.Nodes()) {
|
||||||
{
|
|
||||||
LOCK(cs_vNodes);
|
|
||||||
vNodesCopy = vNodes;
|
|
||||||
for (CNode* pnode : vNodesCopy)
|
|
||||||
pnode->AddRef();
|
|
||||||
}
|
|
||||||
for (CNode* pnode : vNodesCopy)
|
|
||||||
{
|
|
||||||
if (interruptNet)
|
if (interruptNet)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -1606,11 +1600,6 @@ void CConnman::SocketHandler()
|
||||||
|
|
||||||
if (InactivityCheck(*pnode)) pnode->fDisconnect = true;
|
if (InactivityCheck(*pnode)) pnode->fDisconnect = true;
|
||||||
}
|
}
|
||||||
{
|
|
||||||
LOCK(cs_vNodes);
|
|
||||||
for (CNode* pnode : vNodesCopy)
|
|
||||||
pnode->Release();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CConnman::ThreadSocketHandler()
|
void CConnman::ThreadSocketHandler()
|
||||||
|
@ -2224,27 +2213,17 @@ void CConnman::OpenNetworkConnection(const CAddress& addrConnect, bool fCountFai
|
||||||
void CConnman::ThreadMessageHandler()
|
void CConnman::ThreadMessageHandler()
|
||||||
{
|
{
|
||||||
SetSyscallSandboxPolicy(SyscallSandboxPolicy::MESSAGE_HANDLER);
|
SetSyscallSandboxPolicy(SyscallSandboxPolicy::MESSAGE_HANDLER);
|
||||||
FastRandomContext rng;
|
|
||||||
while (!flagInterruptMsgProc)
|
while (!flagInterruptMsgProc)
|
||||||
{
|
{
|
||||||
std::vector<CNode*> vNodesCopy;
|
|
||||||
{
|
|
||||||
LOCK(cs_vNodes);
|
|
||||||
vNodesCopy = vNodes;
|
|
||||||
for (CNode* pnode : vNodesCopy) {
|
|
||||||
pnode->AddRef();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool fMoreWork = false;
|
bool fMoreWork = false;
|
||||||
|
|
||||||
|
{
|
||||||
// Randomize the order in which we process messages from/to our peers.
|
// Randomize the order in which we process messages from/to our peers.
|
||||||
// This prevents attacks in which an attacker exploits having multiple
|
// This prevents attacks in which an attacker exploits having multiple
|
||||||
// consecutive connections in the vNodes list.
|
// consecutive connections in the vNodes list.
|
||||||
Shuffle(vNodesCopy.begin(), vNodesCopy.end(), rng);
|
const NodesSnapshot snap{*this, /*shuffle=*/true};
|
||||||
|
|
||||||
for (CNode* pnode : vNodesCopy)
|
for (CNode* pnode : snap.Nodes()) {
|
||||||
{
|
|
||||||
if (pnode->fDisconnect)
|
if (pnode->fDisconnect)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
@ -2262,11 +2241,6 @@ void CConnman::ThreadMessageHandler()
|
||||||
if (flagInterruptMsgProc)
|
if (flagInterruptMsgProc)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
|
||||||
LOCK(cs_vNodes);
|
|
||||||
for (CNode* pnode : vNodesCopy)
|
|
||||||
pnode->Release();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
WAIT_LOCK(mutexMsgProc, lock);
|
WAIT_LOCK(mutexMsgProc, lock);
|
||||||
|
|
37
src/net.h
37
src/net.h
|
@ -1177,6 +1177,43 @@ private:
|
||||||
*/
|
*/
|
||||||
std::vector<CService> m_onion_binds;
|
std::vector<CService> m_onion_binds;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* RAII helper to atomically create a copy of `vNodes` and add a reference
|
||||||
|
* to each of the nodes. The nodes are released when this object is destroyed.
|
||||||
|
*/
|
||||||
|
class NodesSnapshot
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit NodesSnapshot(const CConnman& connman, bool shuffle)
|
||||||
|
{
|
||||||
|
{
|
||||||
|
LOCK(connman.cs_vNodes);
|
||||||
|
m_nodes_copy = connman.vNodes;
|
||||||
|
for (auto& node : m_nodes_copy) {
|
||||||
|
node->AddRef();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (shuffle) {
|
||||||
|
Shuffle(m_nodes_copy.begin(), m_nodes_copy.end(), FastRandomContext{});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
~NodesSnapshot()
|
||||||
|
{
|
||||||
|
for (auto& node : m_nodes_copy) {
|
||||||
|
node->Release();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::vector<CNode*>& Nodes() const
|
||||||
|
{
|
||||||
|
return m_nodes_copy;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::vector<CNode*> m_nodes_copy;
|
||||||
|
};
|
||||||
|
|
||||||
friend struct CConnmanTest;
|
friend struct CConnmanTest;
|
||||||
friend struct ConnmanTestMsg;
|
friend struct ConnmanTestMsg;
|
||||||
};
|
};
|
||||||
|
|
Loading…
Add table
Reference in a new issue