From acbb783cc196922027874ce8af34af35e0944886 Mon Sep 17 00:00:00 2001 From: Wenzel Jakob Date: Wed, 29 Jul 2026 08:49:49 +0200 Subject: [PATCH 1/2] gh-151728: Clear the typing caches at interpreter shutdown The typing module caches every subscripted type. When an extension module leaks a reference to typing, these caches also keep types owned by other (correct) extension modules alive past interpreter shutdown, where nothing can free them anymore. The cache_clear callables are already collected in typing._cleanups, so registering them with atexit is enough to avoid this. --- Lib/typing.py | 11 +++++++++++ .../2026-07-29-11-05-00.gh-issue-151728.Kq3vTn.rst | 4 ++++ 2 files changed, 15 insertions(+) create mode 100644 Misc/NEWS.d/next/Library/2026-07-29-11-05-00.gh-issue-151728.Kq3vTn.rst diff --git a/Lib/typing.py b/Lib/typing.py index 054420865d7fb50..809c0ff88607a59 100644 --- a/Lib/typing.py +++ b/Lib/typing.py @@ -19,6 +19,7 @@ """ from abc import abstractmethod, ABCMeta +import atexit import collections from collections import defaultdict import collections.abc @@ -392,6 +393,16 @@ def _flatten_literal_params(parameters): _caches = {} +def _clear_caches(): + for cleanup in _cleanups: + cleanup() + + +# Release the LRU caches at shutdown, they otherwise redistribute reference +# leaks of one extension to types of unrelated ones. See GH-151728. +atexit.register(_clear_caches) + + def _tp_cache(func=None, /, *, typed=False): """Internal wrapper caching __getitem__ of generic types. diff --git a/Misc/NEWS.d/next/Library/2026-07-29-11-05-00.gh-issue-151728.Kq3vTn.rst b/Misc/NEWS.d/next/Library/2026-07-29-11-05-00.gh-issue-151728.Kq3vTn.rst new file mode 100644 index 000000000000000..39c63a1aea3193a --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-07-29-11-05-00.gh-issue-151728.Kq3vTn.rst @@ -0,0 +1,4 @@ +Clear the internal :mod:`typing` caches from an exit handler. Previously, an +extension module that leaked a reference to :mod:`typing` would also keep every +subscripted type alive past interpreter shutdown, including types owned by +unrelated extension modules. From 875864e057593c4ce05c2b302a6e7d47cbfcaa28 Mon Sep 17 00:00:00 2001 From: Wenzel Jakob Date: Wed, 29 Jul 2026 14:58:54 +0200 Subject: [PATCH 2/2] Incorporate feedback --- Lib/test/libregrtest/utils.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Lib/test/libregrtest/utils.py b/Lib/test/libregrtest/utils.py index 32f02429ff33076..892d204700179f6 100644 --- a/Lib/test/libregrtest/utils.py +++ b/Lib/test/libregrtest/utils.py @@ -272,8 +272,7 @@ def clear_caches(): except KeyError: pass else: - for f in typing._cleanups: - f() + typing._clear_caches() import inspect abs_classes = filter(inspect.isabstract, typing.__dict__.values())