Log unhandled loop exception traces when asyncio debug is on (#57602)

This commit is contained in:
J. Nick Koston 2021-10-18 17:07:51 -10:00 committed by GitHub
parent f92fe38bbd
commit 6576225c48
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 36 additions and 3 deletions

View File

@ -5,6 +5,7 @@ import asyncio
import dataclasses
import logging
import threading
import traceback
from typing import Any
from homeassistant import bootstrap
@ -86,9 +87,15 @@ def _async_loop_exception_handler(_: Any, context: dict[str, Any]) -> None:
if exception := context.get("exception"):
kwargs["exc_info"] = (type(exception), exception, exception.__traceback__)
logging.getLogger(__package__).error(
"Error doing job: %s", context["message"], **kwargs # type: ignore
)
logger = logging.getLogger(__package__)
if source_traceback := context.get("source_traceback"):
stack_summary = "".join(traceback.format_list(source_traceback))
logger.error(
"Error doing job: %s: %s", context["message"], stack_summary, **kwargs # type: ignore
)
return
logger.error("Error doing job: %s", context["message"], **kwargs) # type: ignore
async def setup_and_run_hass(runtime_config: RuntimeConfig) -> int:

View File

@ -1,5 +1,11 @@
"""List of tests that have uncaught exceptions today. Will be shrunk over time."""
IGNORE_UNCAUGHT_EXCEPTIONS = [
(
# This test explicitly throws an uncaught exception
# and should not be removed.
"tests.test_runner",
"test_unhandled_exception_traceback",
),
(
"test_homeassistant_bridge",
"test_homeassistant_bridge_fan_setup",

View File

@ -117,3 +117,23 @@ def test_run_does_not_block_forever_with_shielded_task(hass, tmpdir, caplog):
assert (
"Task could not be canceled and was still running after shutdown" in caplog.text
)
async def test_unhandled_exception_traceback(hass, caplog):
"""Test an unhandled exception gets a traceback in debug mode."""
async def _unhandled_exception():
raise Exception("This is unhandled")
try:
hass.loop.set_debug(True)
asyncio.create_task(_unhandled_exception())
finally:
hass.loop.set_debug(False)
await asyncio.sleep(0)
await asyncio.sleep(0)
assert "Task exception was never retrieved" in caplog.text
assert "This is unhandled" in caplog.text
assert "_unhandled_exception" in caplog.text