prevent deadlock

This commit is contained in:
Grant Limberg 2023-05-03 16:26:09 -07:00
parent ff2a9c88f0
commit f548905db4
No known key found for this signature in database
GPG key ID: 8F2F97D3BE8D7735

View file

@ -520,67 +520,69 @@ void Peer::performMultipathStateCheck(void *tPtr, int64_t now)
unsigned int Peer::doPingAndKeepalive(void *tPtr,int64_t now) unsigned int Peer::doPingAndKeepalive(void *tPtr,int64_t now)
{ {
unsigned int sent = 0; unsigned int sent = 0;
Mutex::Lock _l(_paths_m); {
Mutex::Lock _l(_paths_m);
performMultipathStateCheck(tPtr, now); performMultipathStateCheck(tPtr, now);
const bool sendFullHello = ((now - _lastSentFullHello) >= ZT_PEER_PING_PERIOD); const bool sendFullHello = ((now - _lastSentFullHello) >= ZT_PEER_PING_PERIOD);
if (sendFullHello) { if (sendFullHello) {
_lastSentFullHello = now; _lastSentFullHello = now;
}
// Right now we only keep pinging links that have the maximum priority. The
// priority is used to track cluster redirections, meaning that when a cluster
// redirects us its redirect target links override all other links and we
// let those old links expire.
long maxPriority = 0;
for(unsigned int i=0;i<ZT_MAX_PEER_NETWORK_PATHS;++i) {
if (_paths[i].p) {
maxPriority = std::max(_paths[i].priority,maxPriority);
} else {
break;
} }
}
bool deletionOccurred = false; // Right now we only keep pinging links that have the maximum priority. The
for(unsigned int i=0;i<ZT_MAX_PEER_NETWORK_PATHS;++i) { // priority is used to track cluster redirections, meaning that when a cluster
if (_paths[i].p) { // redirects us its redirect target links override all other links and we
// Clean expired and reduced priority paths // let those old links expire.
if ( ((now - _paths[i].lr) < ZT_PEER_PATH_EXPIRATION) && (_paths[i].priority == maxPriority) ) { long maxPriority = 0;
if ((sendFullHello)||(_paths[i].p->needsHeartbeat(now))) { for(unsigned int i=0;i<ZT_MAX_PEER_NETWORK_PATHS;++i) {
attemptToContactAt(tPtr,_paths[i].p->localSocket(),_paths[i].p->address(),now,sendFullHello); if (_paths[i].p) {
_paths[i].p->sent(now); maxPriority = std::max(_paths[i].priority,maxPriority);
sent |= (_paths[i].p->address().ss_family == AF_INET) ? 0x1 : 0x2;
}
} else { } else {
_paths[i] = _PeerPath(); break;
deletionOccurred = true;
} }
} }
if (!_paths[i].p || deletionOccurred) {
for(unsigned int j=i;j<ZT_MAX_PEER_NETWORK_PATHS;++j) { bool deletionOccurred = false;
if (_paths[j].p && i != j) { for(unsigned int i=0;i<ZT_MAX_PEER_NETWORK_PATHS;++i) {
_paths[i] = _paths[j]; if (_paths[i].p) {
_paths[j] = _PeerPath(); // Clean expired and reduced priority paths
break; if ( ((now - _paths[i].lr) < ZT_PEER_PATH_EXPIRATION) && (_paths[i].priority == maxPriority) ) {
if ((sendFullHello)||(_paths[i].p->needsHeartbeat(now))) {
attemptToContactAt(tPtr,_paths[i].p->localSocket(),_paths[i].p->address(),now,sendFullHello);
_paths[i].p->sent(now);
sent |= (_paths[i].p->address().ss_family == AF_INET) ? 0x1 : 0x2;
}
} else {
_paths[i] = _PeerPath();
deletionOccurred = true;
} }
} }
deletionOccurred = false; if (!_paths[i].p || deletionOccurred) {
} for(unsigned int j=i;j<ZT_MAX_PEER_NETWORK_PATHS;++j) {
} if (_paths[j].p && i != j) {
uint16_t alive_path_count_tmp = 0, dead_path_count_tmp = 0; _paths[i] = _paths[j];
for(unsigned int i=0;i<ZT_MAX_PEER_NETWORK_PATHS;++i) { _paths[j] = _PeerPath();
if (_paths[i].p) { break;
if (_paths[i].p->alive(now)) { }
alive_path_count_tmp++; }
} deletionOccurred = false;
else {
dead_path_count_tmp++;
} }
} }
uint16_t alive_path_count_tmp = 0, dead_path_count_tmp = 0;
for(unsigned int i=0;i<ZT_MAX_PEER_NETWORK_PATHS;++i) {
if (_paths[i].p) {
if (_paths[i].p->alive(now)) {
alive_path_count_tmp++;
}
else {
dead_path_count_tmp++;
}
}
}
_alive_path_count = alive_path_count_tmp;
_dead_path_count = dead_path_count_tmp;
} }
_alive_path_count = alive_path_count_tmp;
_dead_path_count = dead_path_count_tmp;
_peer_latency.Observe(latency(now)); _peer_latency.Observe(latency(now));
return sent; return sent;
} }