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.
This commit is contained in:
@@ -722,22 +722,30 @@ impl Client {
|
|||||||
username,
|
username,
|
||||||
error,
|
error,
|
||||||
) => {
|
) => {
|
||||||
let context = match client_context.read_safe() {
|
// Scope the read guard: process_failed_uploads
|
||||||
Ok(c) => c,
|
// below acquires a write lock on the same
|
||||||
Err(e) => {
|
// RwLock, which would self-deadlock the entire
|
||||||
error!(
|
// client ops loop if this read guard were still
|
||||||
"[client] PeerDisconnected read: {}",
|
// held on this thread.
|
||||||
e
|
|
||||||
);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
if let Some(ref registry) =
|
|
||||||
context.peer_registry
|
|
||||||
&& let Some(handle) =
|
|
||||||
registry.remove_peer(&username)
|
|
||||||
{
|
{
|
||||||
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 {
|
if let Some(error) = error {
|
||||||
warn!(
|
warn!(
|
||||||
|
|||||||
Reference in New Issue
Block a user