aboutsummaryrefslogtreecommitdiff
path: root/src/net.cpp
diff options
context:
space:
mode:
authorVasil Dimov <vd@FreeBSD.org>2021-04-28 18:29:32 +0200
committerVasil Dimov <vd@FreeBSD.org>2021-11-18 13:38:42 +0100
commit664ac22c5379db65757fc3aab91fff8765683e7f (patch)
tree3198887177c5920ef47f4d9c3d1effc00af6da31 /src/net.cpp
parent75e8bf55f5a014faada7712a9640dc35e8c86f15 (diff)
downloadbitcoin-664ac22c5379db65757fc3aab91fff8765683e7f.tar.xz
net: keep reference to each node during socket wait
Create the snapshot of `CConnman::vNodes` to operate on earlier in `CConnman::SocketHandler()`, before calling `CConnman::SocketEvents()` and pass the `vNodes` copy from the snapshot to `SocketEvents()`. This will keep the refcount of each node incremented during `SocketEvents()` so that the `CNode` object is not destroyed before `SocketEvents()` has finished. Currently in `SocketEvents()` we only remember file descriptor numbers (when not holding `CConnman::cs_vNodes`) which is safe, but we will change this to remember pointers to `CNode::m_sock`.
Diffstat (limited to 'src/net.cpp')
-rw-r--r--src/net.cpp29
1 files changed, 18 insertions, 11 deletions
diff --git a/src/net.cpp b/src/net.cpp
index 165a28c04e..6fab80f976 100644
--- a/src/net.cpp
+++ b/src/net.cpp
@@ -1331,16 +1331,17 @@ bool CConnman::InactivityCheck(const CNode& node) const
return false;
}
-bool CConnman::GenerateSelectSet(std::set<SOCKET> &recv_set, std::set<SOCKET> &send_set, std::set<SOCKET> &error_set)
+bool CConnman::GenerateSelectSet(const std::vector<CNode*>& nodes,
+ std::set<SOCKET>& recv_set,
+ std::set<SOCKET>& send_set,
+ std::set<SOCKET>& error_set)
{
for (const ListenSocket& hListenSocket : vhListenSocket) {
recv_set.insert(hListenSocket.socket);
}
{
- LOCK(cs_vNodes);
- for (CNode* pnode : vNodes)
- {
+ for (CNode* pnode : nodes) {
// Implement the following logic:
// * If there is data to send, select() for sending data. As this only
// happens when optimistic write failed, we choose to first drain the
@@ -1378,10 +1379,13 @@ bool CConnman::GenerateSelectSet(std::set<SOCKET> &recv_set, std::set<SOCKET> &s
}
#ifdef USE_POLL
-void CConnman::SocketEvents(std::set<SOCKET> &recv_set, std::set<SOCKET> &send_set, std::set<SOCKET> &error_set)
+void CConnman::SocketEvents(const std::vector<CNode*>& nodes,
+ std::set<SOCKET>& recv_set,
+ std::set<SOCKET>& send_set,
+ std::set<SOCKET>& error_set)
{
std::set<SOCKET> recv_select_set, send_select_set, error_select_set;
- if (!GenerateSelectSet(recv_select_set, send_select_set, error_select_set)) {
+ if (!GenerateSelectSet(nodes, recv_select_set, send_select_set, error_select_set)) {
interruptNet.sleep_for(std::chrono::milliseconds(SELECT_TIMEOUT_MILLISECONDS));
return;
}
@@ -1420,10 +1424,13 @@ void CConnman::SocketEvents(std::set<SOCKET> &recv_set, std::set<SOCKET> &send_s
}
}
#else
-void CConnman::SocketEvents(std::set<SOCKET> &recv_set, std::set<SOCKET> &send_set, std::set<SOCKET> &error_set)
+void CConnman::SocketEvents(const std::vector<CNode*>& nodes,
+ std::set<SOCKET>& recv_set,
+ std::set<SOCKET>& send_set,
+ std::set<SOCKET>& error_set)
{
std::set<SOCKET> recv_select_set, send_select_set, error_select_set;
- if (!GenerateSelectSet(recv_select_set, send_select_set, error_select_set)) {
+ if (!GenerateSelectSet(nodes, recv_select_set, send_select_set, error_select_set)) {
interruptNet.sleep_for(std::chrono::milliseconds(SELECT_TIMEOUT_MILLISECONDS));
return;
}
@@ -1497,8 +1504,10 @@ void CConnman::SocketEvents(std::set<SOCKET> &recv_set, std::set<SOCKET> &send_s
void CConnman::SocketHandler()
{
+ const NodesSnapshot snap{*this, /*shuffle=*/false};
+
std::set<SOCKET> recv_set, send_set, error_set;
- SocketEvents(recv_set, send_set, error_set);
+ SocketEvents(snap.Nodes(), recv_set, send_set, error_set);
if (interruptNet) return;
@@ -1513,8 +1522,6 @@ void CConnman::SocketHandler()
}
}
- const NodesSnapshot snap{*this, /*shuffle=*/false};
-
//
// Service each socket
//