Skip to content

Commit 22a6c51

Browse files
authored
gh-151728: Clear the typing caches at interpreter shutdown (GH-154858)
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.
1 parent f4b1d3e commit 22a6c51

3 files changed

Lines changed: 16 additions & 2 deletions

File tree

Lib/test/libregrtest/utils.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -272,8 +272,7 @@ def clear_caches():
272272
except KeyError:
273273
pass
274274
else:
275-
for f in typing._cleanups:
276-
f()
275+
typing._clear_caches()
277276

278277
import inspect
279278
abs_classes = filter(inspect.isabstract, typing.__dict__.values())

Lib/typing.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
"""
2020

2121
from abc import abstractmethod, ABCMeta
22+
import atexit
2223
import collections
2324
from collections import defaultdict
2425
import collections.abc
@@ -392,6 +393,16 @@ def _flatten_literal_params(parameters):
392393
_caches = {}
393394

394395

396+
def _clear_caches():
397+
for cleanup in _cleanups:
398+
cleanup()
399+
400+
401+
# Release the LRU caches at shutdown, they otherwise redistribute reference
402+
# leaks of one extension to types of unrelated ones. See GH-151728.
403+
atexit.register(_clear_caches)
404+
405+
395406
def _tp_cache(func=None, /, *, typed=False):
396407
"""Internal wrapper caching __getitem__ of generic types.
397408
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
Clear the internal :mod:`typing` caches from an exit handler. Previously, an
2+
extension module that leaked a reference to :mod:`typing` would also keep every
3+
subscripted type alive past interpreter shutdown, including types owned by
4+
unrelated extension modules.

0 commit comments

Comments
 (0)