diff --git a/src/addrman.cpp b/src/addrman.cpp index 654cea1d2..fa4e866cb 100644 --- a/src/addrman.cpp +++ b/src/addrman.cpp @@ -334,8 +334,10 @@ CAddrInfo CAddrMan::Select_(bool newOnly) if (size() == 0) return CAddrInfo(); - // Track number of attempts to find a table entry, before giving up - int nRetries = 0; + // Track number of attempts to find a table entry, before giving up to avoid infinite loop + const int kMaxRetries = 200000; // magic number so unit tests can pass + const int kRetriesBetweenSleep = 1000; + const int kRetrySleepInterval = 100; // milliseconds if (newOnly && nNew == 0) return CAddrInfo(); @@ -345,12 +347,17 @@ CAddrInfo CAddrMan::Select_(bool newOnly) (nTried > 0 && (nNew == 0 || RandomInt(2) == 0))) { // use a tried node double fChanceFactor = 1.0; - while (nRetries++ < ADDRMAN_TRIED_BUCKET_COUNT) { + while (1) { + int i = 0; int nKBucket = RandomInt(ADDRMAN_TRIED_BUCKET_COUNT); int nKBucketPos = RandomInt(ADDRMAN_BUCKET_SIZE); while (vvTried[nKBucket][nKBucketPos] == -1) { nKBucket = (nKBucket + insecure_rand()) % ADDRMAN_TRIED_BUCKET_COUNT; nKBucketPos = (nKBucketPos + insecure_rand()) % ADDRMAN_BUCKET_SIZE; + if (i++ > kMaxRetries) + return CAddrInfo(); + if (i % kRetriesBetweenSleep == 0) + MilliSleep(kRetrySleepInterval); } int nId = vvTried[nKBucket][nKBucketPos]; assert(mapInfo.count(nId) == 1); @@ -358,17 +365,21 @@ CAddrInfo CAddrMan::Select_(bool newOnly) if (RandomInt(1 << 30) < fChanceFactor * info.GetChance() * (1 << 30)) return info; fChanceFactor *= 1.2; - MilliSleep(100); } } else { // use a new node double fChanceFactor = 1.0; - while (nRetries++ < ADDRMAN_NEW_BUCKET_COUNT) { + while (1) { + int i = 0; int nUBucket = RandomInt(ADDRMAN_NEW_BUCKET_COUNT); int nUBucketPos = RandomInt(ADDRMAN_BUCKET_SIZE); while (vvNew[nUBucket][nUBucketPos] == -1) { nUBucket = (nUBucket + insecure_rand()) % ADDRMAN_NEW_BUCKET_COUNT; nUBucketPos = (nUBucketPos + insecure_rand()) % ADDRMAN_BUCKET_SIZE; + if (i++ > kMaxRetries) + return CAddrInfo(); + if (i % kRetriesBetweenSleep == 0) + MilliSleep(kRetrySleepInterval); } int nId = vvNew[nUBucket][nUBucketPos]; assert(mapInfo.count(nId) == 1); @@ -376,7 +387,6 @@ CAddrInfo CAddrMan::Select_(bool newOnly) if (RandomInt(1 << 30) < fChanceFactor * info.GetChance() * (1 << 30)) return info; fChanceFactor *= 1.2; - MilliSleep(100); } }