From ce4afc567b8328af6de6e7521571c2b0ee75c79e Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Sun, 25 Oct 2026 20:38:18 -0400 Subject: [PATCH] Stop Chromecast discovery when the connect times out The timeout around the blocking Chromecast connect cannot cancel the executor thread. When cast.wait() hangs, the thread never reaches its finally block, so the zeroconf browser keeps running for the life of the process. Stop discovery from the timeout path. Co-authored-by: Paul Robertson Co-Authored-By: Claude Opus 5.5 --- sendspin/serve/chromecast.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/sendspin/serve/chromecast.py b/sendspin/serve/chromecast.py index a061ed6..6cf782e 100644 --- a/sendspin/serve/chromecast.py +++ b/sendspin/serve/chromecast.py @@ -83,11 +83,14 @@ async def connect_to_chromecast( loop = asyncio.get_running_loop() # Connect to Chromecast (blocking call, run in executor) + browsers: list[Any] = [] + def _connect() -> pychromecast.Chromecast: chromecasts, browser = pychromecast.get_chromecasts( known_hosts=[host], zeroconf_instance=zeroconf, ) + browsers.append(browser) try: # Find the Chromecast matching our target host @@ -107,6 +110,9 @@ def _connect() -> pychromecast.Chromecast: timeout=15.0, ) except TimeoutError as e: + # The timeout cannot cancel the executor thread, so stop its discovery here. + for browser in browsers: + browser.stop_discovery() raise TimeoutError(f"Timeout connecting to Chromecast at {host}") from e friendly_name = cast.cast_info.friendly_name or f"Chromecast ({host})"