From e978045a017bce6fb8a7a1afaf01502befe8d168 Mon Sep 17 00:00:00 2001 From: Bart Feenstra Date: Thu, 1 Feb 2024 12:20:14 +0000 Subject: [PATCH] Add a workaround for a bug in Python 3.12 that would randomly cause RuntimeError to be raised when cleaning up thread pools during interpreter shutdown. (#1231) --- betty/__init__.py | 3 +++ betty/_patch.py | 15 +++++++++++++++ 2 files changed, 18 insertions(+) create mode 100644 betty/_patch.py diff --git a/betty/__init__.py b/betty/__init__.py index 75ac22a0e..f0b8579a2 100644 --- a/betty/__init__.py +++ b/betty/__init__.py @@ -1,5 +1,8 @@ """The Betty package root.""" from pathlib import Path +from betty import _patch # noqa: F401 + + # This lives here so it can be imported before any third-party Python modules are available. _ROOT_DIRECTORY_PATH = Path(__file__).resolve().parents[1] diff --git a/betty/_patch.py b/betty/_patch.py new file mode 100644 index 000000000..27571bdfc --- /dev/null +++ b/betty/_patch.py @@ -0,0 +1,15 @@ +from asyncio import BaseEventLoop +from typing import Any + +_original_shutdown_default_executor = BaseEventLoop.shutdown_default_executor + + +async def _shutdown_default_executor(loop: BaseEventLoop, *args: Any, **kwargs: Any) -> None: + try: + await _original_shutdown_default_executor(loop, *args, **kwargs) + except RuntimeError as error: + # Work around a bug in Python 3.12 that will randomly cause a RuntimeError with the + # following message to be raised. + if "can't create new thread at interpreter shutdown" not in str(error): + raise +BaseEventLoop.shutdown_default_executor = _shutdown_default_executor # type: ignore[assignment, method-assign]