Skip to content

Commit 017f047

Browse files
gh-107471: Fix Refleaks in test_import (gh-107569)
gh-107184 introduced a refleak in test_import.SubinterpImportTests (specifically test_singlephase_check_with_setting_and_override and test_single_init_extension_compat). We fix it here by making sure _testsinglephase is removed from sys.modules whenever we clear the runtime's internal state for the module. The underlying problem is strictly contained in the internal function _PyImport_ClearExtension() (AKA _testinternalcapi.clear_extension()), which is only used in tests. (This also fixes an intermittent segfault introduced in the same place, in test_disallowed_reimport.)
1 parent bcdd307 commit 017f047

File tree

2 files changed

+3
-1
lines changed

2 files changed

+3
-1
lines changed

Lib/test/test_import/__init__.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,7 @@ def _ready_to_import(name=None, source=""):
150150
def restore__testsinglephase(*, _orig=_testsinglephase):
151151
# We started with the module imported and want to restore
152152
# it to its nominal state.
153+
sys.modules.pop('_testsinglephase', None)
153154
_orig._clear_globals()
154155
_testinternalcapi.clear_extension('_testsinglephase', _orig.__file__)
155156
import _testsinglephase
@@ -2125,7 +2126,7 @@ def clean_up():
21252126
_interpreters.run_string(interpid, textwrap.dedent(f'''
21262127
name = {self.NAME!r}
21272128
if name in sys.modules:
2128-
sys.modules[name]._clear_globals()
2129+
sys.modules.pop(name)._clear_globals()
21292130
_testinternalcapi.clear_extension(name, {self.FILE!r})
21302131
'''))
21312132
_interpreters.destroy(interpid)

Python/import.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1073,6 +1073,7 @@ _extensions_cache_delete(PyObject *filename, PyObject *name)
10731073
However, this decref would be problematic if the module def were
10741074
dynamically allocated, it were the last ref, and this function
10751075
were called with an interpreter other than the def's owner. */
1076+
assert(_Py_IsImmortal(entry->value));
10761077
entry->value = NULL;
10771078

10781079
finally:

0 commit comments

Comments
 (0)