Skip to content

Commit

Permalink
[3.13] gh-119584: Fix test_import Failed Assertion (gh-119623) (gh-11…
Browse files Browse the repository at this point in the history
…9633)

The fix in gh-119561 introduced an assertion that doesn't hold true if any of the three new test extension modules are loaded more than once.  This is fine normally but breaks if the new test_check_state_first() is run more than once, which happens for refleak checking and with the regrtest --forever flag.  We fix that here by clearing each of the three modules after loading them.  We also tweak a check in _modules_by_index_check().

(cherry picked from commit ae7b176)

Co-authored-by: Eric Snow <ericsnowcurrently@gmail.com>
  • Loading branch information
miss-islington and ericsnowcurrently authored May 27, 2024
1 parent bd9983c commit 660125f
Show file tree
Hide file tree
Showing 3 changed files with 8 additions and 2 deletions.
3 changes: 3 additions & 0 deletions Lib/test/test_import/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2887,12 +2887,15 @@ def test_with_reinit_reloaded(self):

self.assertIs(reloaded.snapshot.cached, reloaded.module)

@unittest.skipIf(_testinternalcapi is None, "requires _testinternalcapi")
def test_check_state_first(self):
for variant in ['', '_with_reinit', '_with_state']:
name = f'{self.NAME}{variant}_check_cache_first'
with self.subTest(name):
mod = self._load_dynamic(name, self.ORIGIN)
self.assertEqual(mod.__name__, name)
sys.modules.pop(name, None)
_testinternalcapi.clear_extension(name, self.ORIGIN)

# Currently, for every single-phrase init module loaded
# in multiple interpreters, those interpreters share a
Expand Down
3 changes: 3 additions & 0 deletions Modules/_testsinglephase.c
Original file line number Diff line number Diff line change
Expand Up @@ -682,6 +682,9 @@ PyInit__testsinglephase_with_state(void)
/* the _testsinglephase_*_check_cache_first modules */
/****************************************************/

/* Each of these modules should only be freshly loaded. That means
clearing the caches and each module def's m_base after each load. */

static struct PyModuleDef _testsinglephase_check_cache_first = {
PyModuleDef_HEAD_INIT,
.m_name = "_testsinglephase_check_cache_first",
Expand Down
4 changes: 2 additions & 2 deletions Python/import.c
Original file line number Diff line number Diff line change
Expand Up @@ -494,7 +494,7 @@ _modules_by_index_check(PyInterpreterState *interp, Py_ssize_t index)
if (MODULES_BY_INDEX(interp) == NULL) {
return "Interpreters module-list not accessible.";
}
if (index > PyList_GET_SIZE(MODULES_BY_INDEX(interp))) {
if (index >= PyList_GET_SIZE(MODULES_BY_INDEX(interp))) {
return "Module index out of bounds.";
}
return NULL;
Expand Down Expand Up @@ -2183,7 +2183,7 @@ clear_singlephase_extension(PyInterpreterState *interp,
/* Clear data set when the module was initially loaded. */
def->m_base.m_init = NULL;
Py_CLEAR(def->m_base.m_copy);
// We leave m_index alone since there's no reason to reset it.
def->m_base.m_index = 0;

/* Clear the PyState_*Module() cache entry. */
Py_ssize_t index = _get_cached_module_index(cached);
Expand Down

0 comments on commit 660125f

Please sign in to comment.