From c5f57ccceaad07486cd6b766e50ff99141a7634b Mon Sep 17 00:00:00 2001 From: michel Date: Sat, 18 Jul 2026 14:37:35 +0200 Subject: [PATCH] fix: resolve self-deadlock in PeerDisconnected handler The handler held a read guard on the client-context RwLock while calling process_failed_uploads, which acquires a write guard on the same lock on the same thread. std RwLock write() then blocks forever, wedging the entire client operations loop. The read guard is now scoped to just the registry cleanup and dropped before the write is taken. --- soulseek-rs-lib/src/client.rs | 38 +++++++++++++++++++++-------------- 1 file changed, 23 insertions(+), 15 deletions(-) diff --git a/soulseek-rs-lib/src/client.rs b/soulseek-rs-lib/src/client.rs index 473c72f..a5b1171 100644 --- a/soulseek-rs-lib/src/client.rs +++ b/soulseek-rs-lib/src/client.rs @@ -722,22 +722,30 @@ impl Client { username, error, ) => { - let context = match client_context.read_safe() { - Ok(c) => c, - Err(e) => { - error!( - "[client] PeerDisconnected read: {}", - e - ); - continue; - } - }; - if let Some(ref registry) = - context.peer_registry - && let Some(handle) = - registry.remove_peer(&username) + // Scope the read guard: process_failed_uploads + // below acquires a write lock on the same + // RwLock, which would self-deadlock the entire + // client ops loop if this read guard were still + // held on this thread. { - let _ = handle.stop(); + let context = + match client_context.read_safe() { + Ok(c) => c, + Err(e) => { + error!( + "[client] PeerDisconnected read: {}", + e + ); + continue; + } + }; + if let Some(ref registry) = + context.peer_registry + && let Some(handle) = + registry.remove_peer(&username) + { + let _ = handle.stop(); + } } if let Some(error) = error { warn!(