Fix backend mutex poisoned panic on OpenHome stop

Fix backend mutex poisoned panic when stopping playback on OpenHome renderer

This commit addresses a panic that occurred when stopping playback on OpenHome renderers, which was caused by:

1. Mutex poisoning from unhandled panics in backend operations
2. A regression revealed after initial fixes, where inconsistent renderer state caused index out of bounds errors

Changes include:
- Added defensive error handling for mutex operations to prevent poisoning
- Implemented bounds-checking for current_index in sync_queue to handle inconsistent renderer states
- Removed redundant clear_queue calls that were causing additional failures
- Improved error tolerance in queue operations

The fix ensures that the backend mutex remains healthy and that inconsistent renderer states are handled gracefully rather than causing panics.
This commit is contained in:
2026-01-17 13:13:35 +01:00
parent d7dcd164c8
commit 4f8f902f3f
9 changed files with 463 additions and 143 deletions

View File

@@ -1,7 +1,7 @@
use std::usize;
use quick_xml::escape::escape;
use tracing::debug;
use tracing::{debug, warn};
use crate::errors::ControlPointError;
use crate::upnp_clients::{
@@ -619,13 +619,26 @@ impl QueueBackend for OpenHomeQueue {
// differences. Without this, any drift between our cache and the renderer
// (e.g., manual edits from another control point) would keep the stale items.
let snapshot = self.queue_snapshot()?;
// Note: current_index may point to an index that doesn't exist in items
// if the OpenHome renderer is in an inconsistent state (e.g., IdArray returns
// IDs but ReadList returns empty TrackList). We must bounds-check here.
let playing_info = snapshot.current_index.and_then(|idx| {
Some((
idx,
snapshot.items[idx].backend_id,
snapshot.items[idx].uri.clone(),
snapshot.items[idx].didl_id.clone(),
))
if idx < snapshot.items.len() {
Some((
idx,
snapshot.items[idx].backend_id,
snapshot.items[idx].uri.clone(),
snapshot.items[idx].didl_id.clone(),
))
} else {
warn!(
renderer = self.renderer_id.0.as_str(),
current_index = idx,
items_len = snapshot.items.len(),
"OpenHome renderer in inconsistent state: current_index out of bounds, treating as no current track"
);
None
}
});
debug!(