Skip to content

Commit 914f8fd

Browse files
gh-59956: Add a Test to Verify GILState Matches the "Current" Thread State (gh-101625)
This test should have been in gh-101431. #59956
1 parent 3875276 commit 914f8fd

File tree

2 files changed

+40
-0
lines changed

2 files changed

+40
-0
lines changed

Lib/test/test_capi/test_misc.py

+3
Original file line numberDiff line numberDiff line change
@@ -1413,6 +1413,9 @@ def callback():
14131413
ret = assert_python_ok('-X', 'tracemalloc', '-c', code)
14141414
self.assertIn(b'callback called', ret.out)
14151415

1416+
def test_gilstate_matches_current(self):
1417+
_testcapi.test_current_tstate_matches()
1418+
14161419

14171420
class Test_testcapi(unittest.TestCase):
14181421
locals().update((name, getattr(_testcapi, name))

Modules/_testcapimodule.c

+37
Original file line numberDiff line numberDiff line change
@@ -1534,6 +1534,42 @@ crash_no_current_thread(PyObject *self, PyObject *Py_UNUSED(ignored))
15341534
return NULL;
15351535
}
15361536

1537+
/* Test that the GILState thread and the "current" thread match. */
1538+
static PyObject *
1539+
test_current_tstate_matches(PyObject *self, PyObject *Py_UNUSED(ignored))
1540+
{
1541+
PyThreadState *orig_tstate = PyThreadState_Get();
1542+
1543+
if (orig_tstate != PyGILState_GetThisThreadState()) {
1544+
PyErr_SetString(PyExc_RuntimeError,
1545+
"current thread state doesn't match GILState");
1546+
return NULL;
1547+
}
1548+
1549+
const char *err = NULL;
1550+
PyThreadState_Swap(NULL);
1551+
PyThreadState *substate = Py_NewInterpreter();
1552+
1553+
if (substate != PyThreadState_Get()) {
1554+
err = "subinterpreter thread state not current";
1555+
goto finally;
1556+
}
1557+
if (substate != PyGILState_GetThisThreadState()) {
1558+
err = "subinterpreter thread state doesn't match GILState";
1559+
goto finally;
1560+
}
1561+
1562+
finally:
1563+
Py_EndInterpreter(substate);
1564+
PyThreadState_Swap(orig_tstate);
1565+
1566+
if (err != NULL) {
1567+
PyErr_SetString(PyExc_RuntimeError, err);
1568+
return NULL;
1569+
}
1570+
Py_RETURN_NONE;
1571+
}
1572+
15371573
/* To run some code in a sub-interpreter. */
15381574
static PyObject *
15391575
run_in_subinterp(PyObject *self, PyObject *args)
@@ -3354,6 +3390,7 @@ static PyMethodDef TestMethods[] = {
33543390
{"make_memoryview_from_NULL_pointer", make_memoryview_from_NULL_pointer,
33553391
METH_NOARGS},
33563392
{"crash_no_current_thread", crash_no_current_thread, METH_NOARGS},
3393+
{"test_current_tstate_matches", test_current_tstate_matches, METH_NOARGS},
33573394
{"run_in_subinterp", run_in_subinterp, METH_VARARGS},
33583395
{"run_in_subinterp_with_config",
33593396
_PyCFunction_CAST(run_in_subinterp_with_config),

0 commit comments

Comments
 (0)