mirror of
https://github.com/home-assistant/core.git
synced 2025-07-18 02:37:08 +00:00
Improve error reporting when an integration tries to create a task in a thread (#115307)
This commit is contained in:
parent
6ed2190c29
commit
f527fd0947
@ -24,12 +24,20 @@ def create_eager_task(
|
|||||||
loop: AbstractEventLoop | None = None,
|
loop: AbstractEventLoop | None = None,
|
||||||
) -> Task[_T]:
|
) -> Task[_T]:
|
||||||
"""Create a task from a coroutine and schedule it to run immediately."""
|
"""Create a task from a coroutine and schedule it to run immediately."""
|
||||||
return Task(
|
if not loop:
|
||||||
coro,
|
try:
|
||||||
loop=loop or get_running_loop(),
|
loop = get_running_loop()
|
||||||
name=name,
|
except RuntimeError:
|
||||||
eager_start=True,
|
# If there is no running loop, create_eager_task is being called from
|
||||||
)
|
# the wrong thread.
|
||||||
|
# Late import to avoid circular dependencies
|
||||||
|
# pylint: disable-next=import-outside-toplevel
|
||||||
|
from homeassistant.helpers import frame
|
||||||
|
|
||||||
|
frame.report("attempted to create an asyncio task from a thread")
|
||||||
|
raise
|
||||||
|
|
||||||
|
return Task(coro, loop=loop, name=name, eager_start=True)
|
||||||
|
|
||||||
|
|
||||||
def cancelling(task: Future[Any]) -> bool:
|
def cancelling(task: Future[Any]) -> bool:
|
||||||
|
@ -9,6 +9,8 @@ import pytest
|
|||||||
from homeassistant.core import HomeAssistant
|
from homeassistant.core import HomeAssistant
|
||||||
from homeassistant.util import async_ as hasync
|
from homeassistant.util import async_ as hasync
|
||||||
|
|
||||||
|
from tests.common import extract_stack_to_frame
|
||||||
|
|
||||||
|
|
||||||
@patch("concurrent.futures.Future")
|
@patch("concurrent.futures.Future")
|
||||||
@patch("threading.get_ident")
|
@patch("threading.get_ident")
|
||||||
@ -123,3 +125,73 @@ async def test_create_eager_task_312(hass: HomeAssistant) -> None:
|
|||||||
assert events == ["eager", "normal"]
|
assert events == ["eager", "normal"]
|
||||||
await task1
|
await task1
|
||||||
await task2
|
await task2
|
||||||
|
|
||||||
|
|
||||||
|
async def test_create_eager_task_from_thread(hass: HomeAssistant) -> None:
|
||||||
|
"""Test we report trying to create an eager task from a thread."""
|
||||||
|
|
||||||
|
def create_task():
|
||||||
|
hasync.create_eager_task(asyncio.sleep(0))
|
||||||
|
|
||||||
|
with pytest.raises(
|
||||||
|
RuntimeError,
|
||||||
|
match=(
|
||||||
|
"Detected code that attempted to create an asyncio task from a thread. Please report this issue."
|
||||||
|
),
|
||||||
|
):
|
||||||
|
await hass.async_add_executor_job(create_task)
|
||||||
|
|
||||||
|
|
||||||
|
async def test_create_eager_task_from_thread_in_integration(
|
||||||
|
hass: HomeAssistant, caplog: pytest.LogCaptureFixture
|
||||||
|
) -> None:
|
||||||
|
"""Test we report trying to create an eager task from a thread."""
|
||||||
|
|
||||||
|
def create_task():
|
||||||
|
hasync.create_eager_task(asyncio.sleep(0))
|
||||||
|
|
||||||
|
frames = extract_stack_to_frame(
|
||||||
|
[
|
||||||
|
Mock(
|
||||||
|
filename="/home/paulus/homeassistant/core.py",
|
||||||
|
lineno="23",
|
||||||
|
line="do_something()",
|
||||||
|
),
|
||||||
|
Mock(
|
||||||
|
filename="/home/paulus/homeassistant/components/hue/light.py",
|
||||||
|
lineno="23",
|
||||||
|
line="self.light.is_on",
|
||||||
|
),
|
||||||
|
Mock(
|
||||||
|
filename="/home/paulus/aiohue/lights.py",
|
||||||
|
lineno="2",
|
||||||
|
line="something()",
|
||||||
|
),
|
||||||
|
]
|
||||||
|
)
|
||||||
|
with (
|
||||||
|
pytest.raises(RuntimeError, match="no running event loop"),
|
||||||
|
patch(
|
||||||
|
"homeassistant.helpers.frame.linecache.getline",
|
||||||
|
return_value="self.light.is_on",
|
||||||
|
),
|
||||||
|
patch(
|
||||||
|
"homeassistant.util.loop._get_line_from_cache",
|
||||||
|
return_value="mock_line",
|
||||||
|
),
|
||||||
|
patch(
|
||||||
|
"homeassistant.util.loop.get_current_frame",
|
||||||
|
return_value=frames,
|
||||||
|
),
|
||||||
|
patch(
|
||||||
|
"homeassistant.helpers.frame.get_current_frame",
|
||||||
|
return_value=frames,
|
||||||
|
),
|
||||||
|
):
|
||||||
|
await hass.async_add_executor_job(create_task)
|
||||||
|
|
||||||
|
assert (
|
||||||
|
"Detected that integration 'hue' attempted to create an asyncio task "
|
||||||
|
"from a thread at homeassistant/components/hue/light.py, line 23: "
|
||||||
|
"self.light.is_on"
|
||||||
|
) in caplog.text
|
||||||
|
Loading…
x
Reference in New Issue
Block a user