Fix RuntimeError from dict/set mutation during iteration (#3159)
* Fix RuntimeError from dict/set mutation during iteration
Several collections are iterated while concurrent callbacks can
modify them, causing "Set/dictionary changed size during iteration"
RuntimeErrors:
- mass.py: _subscribers set iterated in signal_event() while
subscribe/unsubscribe callbacks modify it
- mass.py: _providers dict iterated in get_provider() and
_on_mdns_service_state_change() while providers load/unload
- player_controller.py: _players dict iterated in get_players(),
get_player_by_name(), and update_player_control() while players
register/unregister
- music.py: in_progress_syncs list iterated while done-callbacks
call .remove() on it
Snapshot via list() before iterating in all affected locations.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* Fix additional dict mutation during iteration in mass.py
Snapshot via list() in three more locations where self._providers
or self._tracked_tasks are iterated while concurrent callbacks can
modify them: get_providers(), get_providers_by_domain(), and stop().
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* Fix dict mutation during iteration in webserver dynamic routes
Snapshot self._dynamic_routes.items() via list() in _handle_catch_all()
to prevent RuntimeError when routes are registered or unregistered by
providers while a request is being matched against prefix routes.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
---------
Co-authored-by: David Bishop <git@gnuconsulting.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>