From 1a270257936e4dafb8b7ac8d667757b49661df0a Mon Sep 17 00:00:00 2001 From: Erik Montnemery Date: Tue, 15 Mar 2022 12:46:58 +0100 Subject: [PATCH] Prevent spawning script runs when shutting down (#68170) --- homeassistant/helpers/script.py | 8 ++++++++ tests/helpers/test_script.py | 20 ++++++++++++++++++++ 2 files changed, 28 insertions(+) diff --git a/homeassistant/helpers/script.py b/homeassistant/helpers/script.py index 07a89c8cddb..1de5600f208 100644 --- a/homeassistant/helpers/script.py +++ b/homeassistant/helpers/script.py @@ -110,6 +110,7 @@ ATTR_MAX = "max" DATA_SCRIPTS = "helpers.script" DATA_SCRIPT_BREAKPOINTS = "helpers.script_breakpoints" +DATA_NEW_SCRIPT_RUNS_NOT_ALLOWED = "helpers.script_not_allowed" RUN_ID_ANY = "*" NODE_ANY = "*" @@ -883,6 +884,7 @@ class _QueuedScriptRun(_ScriptRun): async def _async_stop_scripts_after_shutdown(hass, point_in_time): """Stop running Script objects started after shutdown.""" + hass.data[DATA_NEW_SCRIPT_RUNS_NOT_ALLOWED] = None running_scripts = [ script for script in hass.data[DATA_SCRIPTS] if script["instance"].is_running ] @@ -1192,6 +1194,12 @@ class Script: ) context = Context() + # Prevent spawning new script runs when Home Assistant is shutting down + if DATA_NEW_SCRIPT_RUNS_NOT_ALLOWED in self._hass.data: + self._log("Home Assistant is shutting down, starting script blocked") + return + + # Prevent spawning new script runs if not allowed by script mode if self.is_running: if self.script_mode == SCRIPT_MODE_SINGLE: if self._max_exceeded != "SILENT": diff --git a/tests/helpers/test_script.py b/tests/helpers/test_script.py index 11ba9810b9d..03a91ce1261 100644 --- a/tests/helpers/test_script.py +++ b/tests/helpers/test_script.py @@ -3276,6 +3276,26 @@ async def test_shutdown_after(hass, caplog): assert_action_trace(expected_trace) +async def test_start_script_after_shutdown(hass, caplog): + """Test starting scripts after shutdown is blocked.""" + delay_alias = "delay step" + sequence = cv.SCRIPT_SCHEMA({"delay": {"seconds": 120}, "alias": delay_alias}) + script_obj = script.Script(hass, sequence, "test script", "test_domain") + + # Trigger 1st stage script shutdown + hass.state = CoreState.stopping + hass.bus.async_fire("homeassistant_stop") + await hass.async_block_till_done() + # Trigger 2nd stage script shutdown + async_fire_time_changed(hass, dt_util.utcnow() + timedelta(seconds=60)) + await hass.async_block_till_done() + + # Attempt to spawn additional script run + await script_obj.async_run(context=Context()) + assert not script_obj.is_running + assert "Home Assistant is shutting down, starting script blocked" in caplog.text + + async def test_update_logger(hass, caplog): """Test updating logger.""" sequence = cv.SCRIPT_SCHEMA({"event": "test_event"})