From: Maxim Raznatovski Date: Mon, 8 Dec 2025 23:11:24 +0000 (+0100) Subject: Fix race condition when Sendspin player reconnect (#2772) X-Git-Url: https://git.kitaultman.com/?a=commitdiff_plain;h=5b62b900afd4aabe9cc39b20e6d8561c7b203306;p=music-assistant-server.git Fix race condition when Sendspin player reconnect (#2772) --- diff --git a/music_assistant/providers/sendspin/player.py b/music_assistant/providers/sendspin/player.py index f889cda7..8c42ccff 100644 --- a/music_assistant/providers/sendspin/player.py +++ b/music_assistant/providers/sendspin/player.py @@ -597,4 +597,3 @@ class SendspinPlayer(Player): await super().on_unload() self.unsub_event_cb() self.unsub_group_event_cb() - await self.api.disconnect() diff --git a/music_assistant/providers/sendspin/provider.py b/music_assistant/providers/sendspin/provider.py index 2f1ae4c5..66437afb 100644 --- a/music_assistant/providers/sendspin/provider.py +++ b/music_assistant/providers/sendspin/provider.py @@ -43,6 +43,7 @@ class SendspinProvider(PlayerProvider): server_api: SendspinServer unregister_cbs: list[Callable[[], None]] _webrtc_sessions: dict[str, SendspinWebRTCSession] + _pending_unregisters: dict[str, asyncio.Event] def __init__( self, mass: MusicAssistant, manifest: ProviderManifest, config: ProviderConfig @@ -53,6 +54,7 @@ class SendspinProvider(PlayerProvider): self.mass.loop, mass.server_id, "Music Assistant", self.mass.http_session ) self._webrtc_sessions = {} + self._pending_unregisters = {} self.unregister_cbs = [ self.server_api.add_event_listener(self.event_cb), # WebRTC signaling commands for Sendspin connections @@ -72,12 +74,26 @@ class SendspinProvider(PlayerProvider): self.logger.debug("Received SendspinEvent: %s", event) match event: case ClientAddedEvent(client_id): + # Wait for any pending unregister to complete before registering + # This prevents a race condition where a slow unregister removes + # a newly registered player after a quick reconnect + if pending_event := self._pending_unregisters.get(client_id): + self.logger.debug( + "Waiting for pending unregister of %s before registering", client_id + ) + await pending_event.wait() player = SendspinPlayer(self, client_id) self.logger.debug("Client %s connected", client_id) await self.mass.players.register(player) case ClientRemovedEvent(client_id): self.logger.debug("Client %s disconnected", client_id) - await self.mass.players.unregister(client_id) + unregister_event = asyncio.Event() + self._pending_unregisters[client_id] = unregister_event + try: + await self.mass.players.unregister(client_id) + finally: + self._pending_unregisters.pop(client_id, None) + unregister_event.set() case _: self.logger.error("Unknown sendspin event: %s", event)