mirror of
https://github.com/home-assistant/core.git
synced 2025-07-22 20:57:21 +00:00
Fix race in script stop that could cause async_stop to hang forever (#113089)
This commit is contained in:
parent
eff0aac586
commit
324266a4e6
@ -392,6 +392,7 @@ class _ScriptRun:
|
||||
self._context = context
|
||||
self._log_exceptions = log_exceptions
|
||||
self._step = -1
|
||||
self._started = False
|
||||
self._stop = asyncio.Event()
|
||||
self._stopped = asyncio.Event()
|
||||
self._conversation_response: str | None | UndefinedType = UNDEFINED
|
||||
@ -420,6 +421,7 @@ class _ScriptRun:
|
||||
|
||||
async def async_run(self) -> ScriptRunResult | None:
|
||||
"""Run script."""
|
||||
self._started = True
|
||||
# Push the script to the script execution stack
|
||||
if (script_stack := script_stack_cv.get()) is None:
|
||||
script_stack = []
|
||||
@ -501,7 +503,12 @@ class _ScriptRun:
|
||||
async def async_stop(self) -> None:
|
||||
"""Stop script run."""
|
||||
self._stop.set()
|
||||
await self._stopped.wait()
|
||||
# If the script was never started
|
||||
# the stopped event will never be
|
||||
# set because the script will never
|
||||
# start running
|
||||
if self._started:
|
||||
await self._stopped.wait()
|
||||
|
||||
def _handle_exception(
|
||||
self, exception: Exception, continue_on_error: bool, log_exceptions: bool
|
||||
|
@ -4344,7 +4344,7 @@ async def test_script_mode_queued_cancel(hass: HomeAssistant) -> None:
|
||||
await task2
|
||||
|
||||
assert script_obj.is_running
|
||||
assert script_obj.runs == 1
|
||||
assert script_obj.runs == 2
|
||||
|
||||
with pytest.raises(asyncio.CancelledError):
|
||||
task1.cancel()
|
||||
@ -5621,3 +5621,20 @@ async def test_conversation_response_not_set_subscript_if(
|
||||
"1/if/condition/0": [{"result": {"result": var == 1, "entities": []}}],
|
||||
}
|
||||
assert_action_trace(expected_trace)
|
||||
|
||||
|
||||
async def test_stopping_run_before_starting(
|
||||
hass: HomeAssistant, caplog: pytest.LogCaptureFixture
|
||||
) -> None:
|
||||
"""Test stopping a script run before its started."""
|
||||
sequence = cv.SCRIPT_SCHEMA(
|
||||
[
|
||||
{"wait_template": "{{ 'on' == 'off' }}"},
|
||||
]
|
||||
)
|
||||
script_obj = script.Script(hass, sequence, "Test Name", "test_domain")
|
||||
# Tested directly because we are checking for a race in the internals
|
||||
# where the script is stopped before it is started. Previously this
|
||||
# would hang indefinitely.
|
||||
run = script._ScriptRun(hass, script_obj, {}, None, True)
|
||||
await run.async_stop()
|
||||
|
Loading…
x
Reference in New Issue
Block a user