Feature/provider linup manager deadlock fix (#545)

Identified a critical deadlock path in  reconcile_connections where a DashMap iterator held internal shard locks while awaiting an asynchronous
This commit is contained in:
euzu
2026-01-28 12:15:31 +01:00
committed by GitHub
parent 81af252c8c
commit 45fbf91bee
2 changed files with 10 additions and 5 deletions
@@ -631,11 +631,15 @@ impl ProviderLineupManager {
pub async fn reconcile_connections(&self, mut counts: HashMap<Arc<str>, usize>) {
// 1. Synchronize known providers from actual counts.
// This avoids a transient "zero state" by updating each provider in one step.
for entry in &self.provider_connections {
let name = entry.key();
let count = counts.remove(name).unwrap_or(0);
let mut conn = entry.value().write().await;
// We take a snapshot of the keys and locks to avoid holding the DashMap's internal
// shard locks while awaiting the RwLock of each provider. Holding both can lead to deadlocks.
let snapshot: Vec<_> = self.provider_connections.iter()
.map(|e| (e.key().clone(), Arc::clone(e.value())))
.collect();
for (name, conn_lock) in snapshot {
let count = counts.remove(&name).unwrap_or(0);
let mut conn = conn_lock.write().await;
conn.current_connections = count;
if count == 0 {
conn.granted_grace = false;