mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-05-05 17:30:59 +02:00
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`.
This commit is contained in:
parent
75e8bf55f5
commit
664ac22c53
29
src/net.cpp
29
src/net.cpp
@ -1331,16 +1331,17 @@ bool CConnman::InactivityCheck(const CNode& node) const
|
|||||||
return false;
|
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) {
|
for (const ListenSocket& hListenSocket : vhListenSocket) {
|
||||||
recv_set.insert(hListenSocket.socket);
|
recv_set.insert(hListenSocket.socket);
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
LOCK(cs_vNodes);
|
for (CNode* pnode : nodes) {
|
||||||
for (CNode* pnode : vNodes)
|
|
||||||
{
|
|
||||||
// Implement the following logic:
|
// Implement the following logic:
|
||||||
// * If there is data to send, select() for sending data. As this only
|
// * If there is data to send, select() for sending data. As this only
|
||||||
// happens when optimistic write failed, we choose to first drain the
|
// 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
|
#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;
|
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));
|
interruptNet.sleep_for(std::chrono::milliseconds(SELECT_TIMEOUT_MILLISECONDS));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -1420,10 +1424,13 @@ void CConnman::SocketEvents(std::set<SOCKET> &recv_set, std::set<SOCKET> &send_s
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
#else
|
#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;
|
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));
|
interruptNet.sleep_for(std::chrono::milliseconds(SELECT_TIMEOUT_MILLISECONDS));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -1497,8 +1504,10 @@ void CConnman::SocketEvents(std::set<SOCKET> &recv_set, std::set<SOCKET> &send_s
|
|||||||
|
|
||||||
void CConnman::SocketHandler()
|
void CConnman::SocketHandler()
|
||||||
{
|
{
|
||||||
|
const NodesSnapshot snap{*this, /*shuffle=*/false};
|
||||||
|
|
||||||
std::set<SOCKET> recv_set, send_set, error_set;
|
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;
|
if (interruptNet) return;
|
||||||
|
|
||||||
@ -1513,8 +1522,6 @@ void CConnman::SocketHandler()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const NodesSnapshot snap{*this, /*shuffle=*/false};
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// Service each socket
|
// Service each socket
|
||||||
//
|
//
|
||||||
|
29
src/net.h
29
src/net.h
@ -983,8 +983,33 @@ private:
|
|||||||
void NotifyNumConnectionsChanged();
|
void NotifyNumConnectionsChanged();
|
||||||
/** Return true if the peer is inactive and should be disconnected. */
|
/** Return true if the peer is inactive and should be disconnected. */
|
||||||
bool InactivityCheck(const CNode& node) const;
|
bool InactivityCheck(const CNode& node) const;
|
||||||
bool GenerateSelectSet(std::set<SOCKET> &recv_set, std::set<SOCKET> &send_set, std::set<SOCKET> &error_set);
|
|
||||||
void SocketEvents(std::set<SOCKET> &recv_set, std::set<SOCKET> &send_set, std::set<SOCKET> &error_set);
|
/**
|
||||||
|
* Generate a collection of sockets to check for IO readiness.
|
||||||
|
* @param[in] nodes Select from these nodes' sockets.
|
||||||
|
* @param[out] recv_set Sockets to check for read readiness.
|
||||||
|
* @param[out] send_set Sockets to check for write readiness.
|
||||||
|
* @param[out] error_set Sockets to check for errors.
|
||||||
|
* @return true if at least one socket is to be checked (the returned set is not empty)
|
||||||
|
*/
|
||||||
|
bool GenerateSelectSet(const std::vector<CNode*>& nodes,
|
||||||
|
std::set<SOCKET>& recv_set,
|
||||||
|
std::set<SOCKET>& send_set,
|
||||||
|
std::set<SOCKET>& error_set);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check which sockets are ready for IO.
|
||||||
|
* @param[in] nodes Select from these nodes' sockets.
|
||||||
|
* @param[out] recv_set Sockets which are ready for read.
|
||||||
|
* @param[out] send_set Sockets which are ready for write.
|
||||||
|
* @param[out] error_set Sockets which have errors.
|
||||||
|
* This calls `GenerateSelectSet()` to gather a list of sockets to check.
|
||||||
|
*/
|
||||||
|
void SocketEvents(const std::vector<CNode*>& nodes,
|
||||||
|
std::set<SOCKET>& recv_set,
|
||||||
|
std::set<SOCKET>& send_set,
|
||||||
|
std::set<SOCKET>& error_set);
|
||||||
|
|
||||||
void SocketHandler();
|
void SocketHandler();
|
||||||
void ThreadSocketHandler();
|
void ThreadSocketHandler();
|
||||||
void ThreadDNSAddressSeed();
|
void ThreadDNSAddressSeed();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user