Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
123 changes: 65 additions & 58 deletions src/net.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1240,70 +1240,74 @@ void CConnman::AcceptConnection(const ListenSocket& hListenSocket) {
}
}

void CConnman::ThreadSocketHandler()
void CConnman::DisconnectAndDeleteNodes(bool fDisconectAll)
{
unsigned int nPrevNodeCount = 0;
while (!interruptNet)
//
// Disconnect nodes
//
{
//
// Disconnect nodes
//
LOCK(cs_vNodes);
std::vector<CNode*> vNodesCopy = vNodes;
for (CNode* pnode : vNodesCopy)
{
LOCK(cs_vNodes);
// Disconnect unused nodes
std::vector<CNode*> vNodesCopy = vNodes;
for (CNode* pnode : vNodesCopy)
if (pnode->fDisconnect || fDisconectAll)
{
if (pnode->fDisconnect)
{
if (fLogIPs) {
LogPrintf("ThreadSocketHandler -- removing node: peer=%d addr=%s nRefCount=%d fInbound=%d fMasternode=%d\n",
pnode->GetId(), pnode->addr.ToString(), pnode->GetRefCount(), pnode->fInbound, pnode->fMasternode);
} else {
LogPrintf("ThreadSocketHandler -- removing node: peer=%d nRefCount=%d fInbound=%d fMasternode=%d\n",
pnode->GetId(), pnode->GetRefCount(), pnode->fInbound, pnode->fMasternode);
}
if (fLogIPs) {
LogPrintf("%s -- removing node: peer=%d addr=%s nRefCount=%d fInbound=%d fMasternode=%d\n",
__func__, pnode->GetId(), pnode->addr.ToString(), pnode->GetRefCount(), pnode->fInbound, pnode->fMasternode);
} else {
LogPrintf("%s -- removing node: peer=%d nRefCount=%d fInbound=%d fMasternode=%d\n",
__func__, pnode->GetId(), pnode->GetRefCount(), pnode->fInbound, pnode->fMasternode);
}

// remove from vNodes
vNodes.erase(remove(vNodes.begin(), vNodes.end(), pnode), vNodes.end());
// remove from vNodes
vNodes.erase(remove(vNodes.begin(), vNodes.end(), pnode), vNodes.end());

// release outbound grant (if any)
pnode->grantOutbound.Release();
pnode->grantMasternodeOutbound.Release();
// release outbound grant (if any)
pnode->grantOutbound.Release();
pnode->grantMasternodeOutbound.Release();

// close socket and cleanup
pnode->CloseSocketDisconnect();
// close socket and cleanup
pnode->CloseSocketDisconnect();

// hold in disconnected pool until all refs are released
pnode->Release();
vNodesDisconnected.push_back(pnode);
}
// hold in disconnected pool until all refs are released
pnode->Release();
vNodesDisconnected.push_back(pnode);
}
}
{
// Delete disconnected nodes
std::list<CNode*> vNodesDisconnectedCopy = vNodesDisconnected;
for (CNode* pnode : vNodesDisconnectedCopy)
}
// Delete disconnected nodes
std::list<CNode*> vNodesDisconnectedCopy = vNodesDisconnected;
for (CNode* pnode : vNodesDisconnectedCopy)
{
// wait until threads are done using it
if (pnode->GetRefCount() <= 0) {
bool fDelete = false;
{
// wait until threads are done using it
if (pnode->GetRefCount() <= 0) {
bool fDelete = false;
{
TRY_LOCK(pnode->cs_inventory, lockInv);
if (lockInv) {
TRY_LOCK(pnode->cs_vSend, lockSend);
if (lockSend) {
fDelete = true;
}
}
}
if (fDelete) {
vNodesDisconnected.remove(pnode);
DeleteNode(pnode);
TRY_LOCK(pnode->cs_inventory, lockInv);
if (lockInv) {
TRY_LOCK(pnode->cs_vSend, lockSend);
if (lockSend) {
fDelete = true;
}
}
}
if (fDelete) {
vNodesDisconnected.remove(pnode);
DeleteNode(pnode);
}
}
}
}

void CConnman::ThreadSocketHandler()
{
unsigned int nPrevNodeCount = 0;
while (!interruptNet)
{
// Disconnect unused nodes
DisconnectAndDeleteNodes(false);

size_t vNodesSize;
{
LOCK(cs_vNodes);
Expand Down Expand Up @@ -2735,21 +2739,24 @@ void CConnman::Stop()
fAddressesInitialized = false;
}

// Try to disconnect and delete all nodes
// TODO: it looks like smth is holding nodes sometimes not releasing references properly,
// so we only try a few times here (cause otherwise we might end up waiting forever).
for (int i = 0; i < 10; ++i) {
DisconnectAndDeleteNodes(true);
if (vNodesDisconnected.empty()) {
// All nodes were disconected and deleted, no need to loop any further
break;
}
MilliSleep(100);
}

// Close sockets
for (CNode* pnode : vNodes)
pnode->CloseSocketDisconnect();
for (ListenSocket& hListenSocket : vhListenSocket)
if (hListenSocket.socket != INVALID_SOCKET)
if (!CloseSocket(hListenSocket.socket))
LogPrintf("CloseSocket(hListenSocket) failed with error %s\n", NetworkErrorString(WSAGetLastError()));

// clean up some globals (to help leak detection)
for (CNode *pnode : vNodes) {
DeleteNode(pnode);
}
for (CNode *pnode : vNodesDisconnected) {
DeleteNode(pnode);
}
vNodes.clear();
vNodesDisconnected.clear();
vhListenSocket.clear();
Expand Down
1 change: 1 addition & 0 deletions src/net.h
Original file line number Diff line number Diff line change
Expand Up @@ -470,6 +470,7 @@ class CConnman
void ThreadOpenConnections(std::vector<std::string> connect);
void ThreadMessageHandler();
void AcceptConnection(const ListenSocket& hListenSocket);
void DisconnectAndDeleteNodes(bool fDisconectAll);
void ThreadSocketHandler();
void ThreadDNSAddressSeed();
void ThreadOpenMasternodeConnections();
Expand Down