Skip to content

Commit 15d48ae

Browse files
gh-121110: Fix Extension Module Tests Under Py_TRACE_REFS Builds (gh-121503)
The change in gh-118157 (b2cd54a) should have also updated clear_singlephase_extension() but didn't. We fix that here. Note that clear_singlephase_extension() (AKA _PyImport_ClearExtension()) is only used in tests.
1 parent 218edaf commit 15d48ae

File tree

2 files changed

+43
-26
lines changed

2 files changed

+43
-26
lines changed

Lib/test/test_import/__init__.py

-7
Original file line numberDiff line numberDiff line change
@@ -3034,13 +3034,6 @@ def test_basic_multiple_interpreters_deleted_no_reset(self):
30343034
def test_basic_multiple_interpreters_reset_each(self):
30353035
# resetting between each interpreter
30363036

3037-
if Py_TRACE_REFS:
3038-
# It's a Py_TRACE_REFS build.
3039-
# This test breaks interpreter isolation a little,
3040-
# which causes problems on Py_TRACE_REF builds.
3041-
# See gh-121110.
3042-
raise unittest.SkipTest('crashes on Py_TRACE_REFS builds')
3043-
30443037
# At this point:
30453038
# * alive in 0 interpreters
30463039
# * module def may or may not be loaded already

Python/import.c

+43-19
Original file line numberDiff line numberDiff line change
@@ -1532,6 +1532,35 @@ switch_to_main_interpreter(PyThreadState *tstate)
15321532
return main_tstate;
15331533
}
15341534

1535+
static void
1536+
switch_back_from_main_interpreter(PyThreadState *tstate,
1537+
PyThreadState *main_tstate,
1538+
PyObject *tempobj)
1539+
{
1540+
assert(main_tstate == PyThreadState_GET());
1541+
assert(_Py_IsMainInterpreter(main_tstate->interp));
1542+
assert(tstate->interp != main_tstate->interp);
1543+
1544+
/* Handle any exceptions, which we cannot propagate directly
1545+
* to the subinterpreter. */
1546+
if (PyErr_Occurred()) {
1547+
if (PyErr_ExceptionMatches(PyExc_MemoryError)) {
1548+
/* We trust it will be caught again soon. */
1549+
PyErr_Clear();
1550+
}
1551+
else {
1552+
/* Printing the exception should be sufficient. */
1553+
PyErr_PrintEx(0);
1554+
}
1555+
}
1556+
1557+
Py_XDECREF(tempobj);
1558+
1559+
PyThreadState_Clear(main_tstate);
1560+
(void)PyThreadState_Swap(tstate);
1561+
PyThreadState_Delete(main_tstate);
1562+
}
1563+
15351564
static PyObject *
15361565
get_core_module_dict(PyInterpreterState *interp,
15371566
PyObject *name, PyObject *path)
@@ -2027,27 +2056,10 @@ import_run_extension(PyThreadState *tstate, PyModInitFunction p0,
20272056
/* Switch back to the subinterpreter. */
20282057
if (switched) {
20292058
assert(main_tstate != tstate);
2030-
2031-
/* Handle any exceptions, which we cannot propagate directly
2032-
* to the subinterpreter. */
2033-
if (PyErr_Occurred()) {
2034-
if (PyErr_ExceptionMatches(PyExc_MemoryError)) {
2035-
/* We trust it will be caught again soon. */
2036-
PyErr_Clear();
2037-
}
2038-
else {
2039-
/* Printing the exception should be sufficient. */
2040-
PyErr_PrintEx(0);
2041-
}
2042-
}
2043-
2059+
switch_back_from_main_interpreter(tstate, main_tstate, mod);
20442060
/* Any module we got from the init function will have to be
20452061
* reloaded in the subinterpreter. */
2046-
Py_CLEAR(mod);
2047-
2048-
PyThreadState_Clear(main_tstate);
2049-
(void)PyThreadState_Swap(tstate);
2050-
PyThreadState_Delete(main_tstate);
2062+
mod = NULL;
20512063
}
20522064

20532065
/*****************************************************************/
@@ -2141,9 +2153,21 @@ clear_singlephase_extension(PyInterpreterState *interp,
21412153
}
21422154
}
21432155

2156+
/* We must use the main interpreter to clean up the cache.
2157+
* See the note in import_run_extension(). */
2158+
PyThreadState *tstate = PyThreadState_GET();
2159+
PyThreadState *main_tstate = switch_to_main_interpreter(tstate);
2160+
if (main_tstate == NULL) {
2161+
return -1;
2162+
}
2163+
21442164
/* Clear the cached module def. */
21452165
_extensions_cache_delete(path, name);
21462166

2167+
if (main_tstate != tstate) {
2168+
switch_back_from_main_interpreter(tstate, main_tstate, NULL);
2169+
}
2170+
21472171
return 0;
21482172
}
21492173

0 commit comments

Comments
 (0)