Skip to content

Bug: Thread pool exhaustion caused by synchronous FlightRadar24 API calls in Coordinator #179

@skircr115

Description

@skircr115

Describe the bug
The Problem: The integration wraps the synchronous FlightRadar24API library (which uses the requests library) inside async_add_executor_job. This results in blocking I/O on SyncWorker threads.

On a 10-second polling interval, any network latency or API hang causes these threads to lock up. While these calls usually resolve in 0.2–0.3s, latency spikes (which I have observed up to 3.4s) cause a cascade failure. Because Home Assistant has a finite number of executor threads, these "zombie threads" quickly exhaust the pool, starving other cloud-based integrations and causing system-wide Unclosed connection or Session is closed errors.

Code Analysis: In init.py, the setup and coordinator rely on blocking executor jobs:

await hass.async_add_executor_job(client.login, username, password)
# ...
await coordinator.async_config_entry_first_refresh()

Why this blocks the whole system:

  1. No Async timeouts: Synchronous requests do not respect Home Assistant’s async timeouts, holding threads indefinitely during a hang.
  2. Worker Starvation: Once the SyncWorker pool is saturated with socket.read tasks, no other synchronous tasks in the system can trigger.
  3. Shutdown Deadlock: During shutdown, HA hangs while waiting for these blocking threads to join, eventually requiring a hard process kill.

Logs
The traceback confirms the system is hanging at the socket level inside requests within that executor job:

File "/usr/local/lib/python3.13/site-packages/FlightRadar24/api.py", line 429, in get_flight_details
    response = APIRequest(...)
File "/usr/local/lib/python3.13/site-packages/requests/api.py", line 73, in get
...
File "/usr/local/lib/python3.13/socket.py", line 719, in readinto

Suggested Fix:

  1. Primary Fix: Migrate the underlying FlightRadar24 library from requests to aiohttp. This allows the integration to stay on the MainThread using async_with aiohttp.ClientSession().
  2. Secondary/Immediate Fix: If remaining synchronous, wrap the executor_job with a strict asyncio.wait_for timeout and ensure the API client is initialized with a short timeout (e.g., 5s) to prevent threads from hanging.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions