Skip to content

gh-151728: Clear the typing caches at interpreter shutdown - #154858

Merged
encukou merged 2 commits into
python:mainfrom
wjakob:gh-151728-typing-clear-caches
Jul 30, 2026
Merged

gh-151728: Clear the typing caches at interpreter shutdown#154858
encukou merged 2 commits into
python:mainfrom
wjakob:gh-151728-typing-clear-caches

Conversation

@wjakob

@wjakob wjakob commented Jul 29, 2026

Copy link
Copy Markdown
Contributor

typing caches every subscripted type in module-level lru_cachees. Those caches are only released when the typing module itself is torn down, which does not happen when some extension module leaks a reference to it. Since typing is nearly universal, a single such leak (e.g. via torch) keeps the cached types alive past interpreter shutdown, including types owned by unrelated, correctly written extensions. Those extensions then look like they are leaking: valgrind reports them, and nanobind prints warnings about types, functions, and instances that were never freed.

typing._cleanups already holds callables to clean caches but does nothing with them. This PR registers an atexit callback that triggers them during Python finalization so that the process is leak-free upon termination. This complements gh-98253, which broke a cycle inside _tp_cache but left the retention itself in place.

The PR adds no tests because reproducing the problem requires an extension module that deliberately leaks a reference (i.e. one with a missing tp_traverse). A minimal one is at https://github.com/wjakob/typing-leak.

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.
@wjakob
wjakob force-pushed the gh-151728-typing-clear-caches branch from a191941 to acbb783 Compare July 29, 2026 07:38
@encukou

encukou commented Jul 29, 2026

Copy link
Copy Markdown
Member

Looks reasonable.
Now that there's a function around the loop, could you call it in Lib/test/libregrtest/utils.py (in clear_caches, near the end)?

@wjakob

wjakob commented Jul 29, 2026

Copy link
Copy Markdown
Contributor Author

Done.

@ZeroIntensity

Copy link
Copy Markdown
Member

Quick thought: Should we perhaps add this to sys._clear_internal_caches, and then call that at shutdown instead?

If not, this looks good to me anyway.

@encukou

encukou commented Jul 30, 2026

Copy link
Copy Markdown
Member

Should we perhaps add this to sys._clear_internal_cache

sys is for interpreter internals, I don't think it should be responsible for cleaning up typing.
Maybe we should have a generic module cleanup mechanism, but then again, atexit should be enough.

@encukou
encukou merged commit 22a6c51 into python:main Jul 30, 2026
59 checks passed
@wjakob
wjakob deleted the gh-151728-typing-clear-caches branch July 30, 2026 12:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants