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.)
This commit is contained in:
Eric Snow 2023-08-02 14:55:09 -06:00 committed by GitHub
parent bcdd307231
commit 017f047183
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 3 additions and 1 deletions

View file

@ -150,6 +150,7 @@ if _testsinglephase is not None:
def restore__testsinglephase(*, _orig=_testsinglephase): def restore__testsinglephase(*, _orig=_testsinglephase):
# We started with the module imported and want to restore # We started with the module imported and want to restore
# it to its nominal state. # it to its nominal state.
sys.modules.pop('_testsinglephase', None)
_orig._clear_globals() _orig._clear_globals()
_testinternalcapi.clear_extension('_testsinglephase', _orig.__file__) _testinternalcapi.clear_extension('_testsinglephase', _orig.__file__)
import _testsinglephase import _testsinglephase
@ -2125,7 +2126,7 @@ class SinglephaseInitTests(unittest.TestCase):
_interpreters.run_string(interpid, textwrap.dedent(f''' _interpreters.run_string(interpid, textwrap.dedent(f'''
name = {self.NAME!r} name = {self.NAME!r}
if name in sys.modules: if name in sys.modules:
sys.modules[name]._clear_globals() sys.modules.pop(name)._clear_globals()
_testinternalcapi.clear_extension(name, {self.FILE!r}) _testinternalcapi.clear_extension(name, {self.FILE!r})
''')) '''))
_interpreters.destroy(interpid) _interpreters.destroy(interpid)

View file

@ -1073,6 +1073,7 @@ _extensions_cache_delete(PyObject *filename, PyObject *name)
However, this decref would be problematic if the module def were However, this decref would be problematic if the module def were
dynamically allocated, it were the last ref, and this function dynamically allocated, it were the last ref, and this function
were called with an interpreter other than the def's owner. */ were called with an interpreter other than the def's owner. */
assert(_Py_IsImmortal(entry->value));
entry->value = NULL; entry->value = NULL;
finally: finally: