gh-98253: Break potential reference cycles in external code worsened by typing.py lru_cache (#98591)

This commit is contained in:
Wenzel Jakob 2022-11-30 09:33:32 +01:00 committed by GitHub
parent 8bb2303fd7
commit c314198fad
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 21 additions and 3 deletions

View file

@ -325,6 +325,7 @@ def _flatten_literal_params(parameters):
_cleanups = []
_caches = {}
def _tp_cache(func=None, /, *, typed=False):
@ -332,13 +333,20 @@ def _tp_cache(func=None, /, *, typed=False):
original function for non-hashable arguments.
"""
def decorator(func):
cached = functools.lru_cache(typed=typed)(func)
_cleanups.append(cached.cache_clear)
# The callback 'inner' references the newly created lru_cache
# indirectly by performing a lookup in the global '_caches' dictionary.
# This breaks a reference that can be problematic when combined with
# C API extensions that leak references to types. See GH-98253.
cache = functools.lru_cache(typed=typed)(func)
_caches[func] = cache
_cleanups.append(cache.cache_clear)
del cache
@functools.wraps(func)
def inner(*args, **kwds):
try:
return cached(*args, **kwds)
return _caches[func](*args, **kwds)
except TypeError:
pass # All real errors (not unhashable args) are raised below.
return func(*args, **kwds)