diff options
author | Cory Fields <cory-nospam-@coryfields.com> | 2017-02-06 02:34:57 -0500 |
---|---|---|
committer | Matt Corallo <git@bluematt.me> | 2017-02-10 11:32:39 -0500 |
commit | 321d0fc6b6624c65508f8b9059418cb936f0bbbe (patch) | |
tree | 57a99a1ede16e5449db2d230ddbc7a3b561547be | |
parent | 2447c1024e6069bfe62ddff65c4e1aaf28f32b38 (diff) |
net: fix a few races. Credit @TheBlueMatt
These are (afaik) all long-standing races or concurrent accesses. Going
forward, we can clean these up so that they're not all individual atomic
accesses.
- Reintroduce cs_vRecv to guard receive-specific vars
- Lock vRecv/vSend for CNodeStats
- Make some vars atomic.
- Only set the connection time in CNode's constructor so that it doesn't change
-rw-r--r-- | src/net.cpp | 16 | ||||
-rw-r--r-- | src/net.h | 19 | ||||
-rw-r--r-- | src/net_processing.cpp | 2 |
3 files changed, 22 insertions, 15 deletions
diff --git a/src/net.cpp b/src/net.cpp index 7c45cff1dd..c96ca469ff 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -389,7 +389,6 @@ CNode* CConnman::ConnectNode(CAddress addrConnect, const char *pszDest, bool fCo uint64_t nonce = GetDeterministicRandomizer(RANDOMIZER_ID_LOCALHOSTNONCE).Write(id).Finalize(); CNode* pnode = new CNode(id, nLocalServices, GetBestHeight(), hSocket, addrConnect, CalculateKeyedNetGroup(addrConnect), nonce, pszDest ? pszDest : "", false); pnode->nServicesExpected = ServiceFlags(addrConnect.nServices & nRelevantServices); - pnode->nTimeConnected = GetSystemTimeInSeconds(); pnode->AddRef(); return pnode; @@ -612,10 +611,16 @@ void CNode::copyStats(CNodeStats &stats) X(fInbound); X(fAddnode); X(nStartingHeight); - X(nSendBytes); - X(mapSendBytesPerMsgCmd); - X(nRecvBytes); - X(mapRecvBytesPerMsgCmd); + { + LOCK(cs_vSend); + X(mapSendBytesPerMsgCmd); + X(nSendBytes); + } + { + LOCK(cs_vRecv); + X(mapRecvBytesPerMsgCmd); + X(nRecvBytes); + } X(fWhitelisted); // It is common for nodes with good ping times to suddenly become lagged, @@ -643,6 +648,7 @@ bool CNode::ReceiveMsgBytes(const char *pch, unsigned int nBytes, bool& complete { complete = false; int64_t nTimeMicros = GetTimeMicros(); + LOCK(cs_vRecv); nLastRecv = nTimeMicros / 1000000; nRecvBytes += nBytes; while (nBytes > 0) { @@ -573,6 +573,7 @@ public: std::deque<std::vector<unsigned char>> vSendMsg; CCriticalSection cs_vSend; CCriticalSection cs_hSocket; + CCriticalSection cs_vRecv; CCriticalSection cs_vProcessMsg; std::list<CNetMessage> vProcessMsg; @@ -584,10 +585,10 @@ public: uint64_t nRecvBytes; std::atomic<int> nRecvVersion; - int64_t nLastSend; - int64_t nLastRecv; + std::atomic<int64_t> nLastSend; + std::atomic<int64_t> nLastRecv; int64_t nTimeConnected; - int64_t nTimeOffset; + std::atomic<int64_t> nTimeOffset; const CAddress addr; std::string addrName; CService addrLocal; @@ -614,7 +615,7 @@ public: CSemaphoreGrant grantOutbound; CCriticalSection cs_filter; CBloomFilter* pfilter; - int nRefCount; + std::atomic<int> nRefCount; const NodeId id; const uint64_t nKeyedNetGroup; @@ -665,15 +666,15 @@ public: // Ping time measurement: // The pong reply we're expecting, or 0 if no pong expected. - uint64_t nPingNonceSent; + std::atomic<uint64_t> nPingNonceSent; // Time (in usec) the last ping was sent, or 0 if no ping was ever sent. - int64_t nPingUsecStart; + std::atomic<int64_t> nPingUsecStart; // Last measured round-trip time. - int64_t nPingUsecTime; + std::atomic<int64_t> nPingUsecTime; // Best measured round-trip time. - int64_t nMinPingUsecTime; + std::atomic<int64_t> nMinPingUsecTime; // Whether a ping is requested. - bool fPingQueued; + std::atomic<bool> fPingQueued; // Minimum fee rate with which to filter inv's to this node CAmount minFeeFilter; CCriticalSection cs_feeFilter; diff --git a/src/net_processing.cpp b/src/net_processing.cpp index bb14e69d83..e89a897bd5 100644 --- a/src/net_processing.cpp +++ b/src/net_processing.cpp @@ -2450,7 +2450,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr if (pingUsecTime > 0) { // Successful ping time measurement, replace previous pfrom->nPingUsecTime = pingUsecTime; - pfrom->nMinPingUsecTime = std::min(pfrom->nMinPingUsecTime, pingUsecTime); + pfrom->nMinPingUsecTime = std::min(pfrom->nMinPingUsecTime.load(), pingUsecTime); } else { // This should never happen sProblem = "Timing mishap"; |