mirror of
https://github.com/home-assistant/supervisor.git
synced 2026-10-01 01:53:43 +01:00
In #7189 a manual POST /core/start during app boot produced a Core that could not bind its own port: the boot flow in Core.start() still held the transient systemd socket reserving it, and only that flow knew how to release it. #7194 closed the API vector by rejecting such calls while Supervisor is not RUNNING, but the guarantee then rests on the API gate rather than on the reservation itself -- any new or ungated path that starts Core reopens the race. Move the reservation onto HomeAssistantCore, which owns the container it protects. reserve_port() is called by the boot flow as before; release_port() is now also called by HomeAssistantCore.start() and restart() right before the container is started, so whichever path gets to Core first gives the port back. rebuild(), update() and the watchdog all funnel through those two. release_port() is a no-op unless a reservation is actually held, so the common case adds no D-Bus traffic. The boot flow keeps its explicit release after the services phase so application-phase apps see the same behavior as before when Core boot is disabled, and its finally block still acts as the backstop. Tests for the systemd interaction move alongside the code to tests/homeassistant/test_core.py; the boot-ordering tests in tests/test_core.py stay and are adapted to the new API. New tests cover start() and restart() releasing a held reservation before the container is touched, start() with no reservation not touching systemd, and start() proceeding when the release cannot be confirmed. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>