Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 914f8fd

Browse filesBrowse 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
Copy full SHA for 914f8fd

File tree

Expand file treeCollapse file tree

2 files changed

+40
-0
lines changed
Filter options
Expand file treeCollapse file tree

2 files changed

+40
-0
lines changed

‎Lib/test/test_capi/test_misc.py

Copy file name to clipboardExpand all lines: Lib/test/test_capi/test_misc.py
+3Lines changed: 3 additions & 0 deletions
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

Copy file name to clipboardExpand all lines: Modules/_testcapimodule.c
+37Lines changed: 37 additions & 0 deletions
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 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.