summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEric Snow <ericsnowcurrently@gmail.com>2023-02-06 22:53:31 (GMT)
committerGitHub <noreply@github.com>2023-02-06 22:53:31 (GMT)
commit914f8fd9f7fc5e48b54d938a68c932cc618ef3a6 (patch)
tree77f87c6c45f28a9795116b89c6fd7f2e2dd13306
parent38752760c91c87dd67af16d2cee611a22e647567 (diff)
downloadcpython-914f8fd9f7fc5e48b54d938a68c932cc618ef3a6.zip
cpython-914f8fd9f7fc5e48b54d938a68c932cc618ef3a6.tar.gz
cpython-914f8fd9f7fc5e48b54d938a68c932cc618ef3a6.tar.bz2
gh-59956: Add a Test to Verify GILState Matches the "Current" Thread State (gh-101625)
This test should have been in gh-101431. https://github.com/python/cpython/issues/59956
-rw-r--r--Lib/test/test_capi/test_misc.py3
-rw-r--r--Modules/_testcapimodule.c37
2 files changed, 40 insertions, 0 deletions
diff --git a/Lib/test/test_capi/test_misc.py b/Lib/test/test_capi/test_misc.py
index dace37c..03e22d7 100644
--- a/Lib/test/test_capi/test_misc.py
+++ b/Lib/test/test_capi/test_misc.py
@@ -1413,6 +1413,9 @@ class TestThreadState(unittest.TestCase):
ret = assert_python_ok('-X', 'tracemalloc', '-c', code)
self.assertIn(b'callback called', ret.out)
+ def test_gilstate_matches_current(self):
+ _testcapi.test_current_tstate_matches()
+
class Test_testcapi(unittest.TestCase):
locals().update((name, getattr(_testcapi, name))
diff --git a/Modules/_testcapimodule.c b/Modules/_testcapimodule.c
index f0d6e40..5e47f49 100644
--- a/Modules/_testcapimodule.c
+++ b/Modules/_testcapimodule.c
@@ -1534,6 +1534,42 @@ crash_no_current_thread(PyObject *self, PyObject *Py_UNUSED(ignored))
return NULL;
}
+/* Test that the GILState thread and the "current" thread match. */
+static PyObject *
+test_current_tstate_matches(PyObject *self, PyObject *Py_UNUSED(ignored))
+{
+ PyThreadState *orig_tstate = PyThreadState_Get();
+
+ if (orig_tstate != PyGILState_GetThisThreadState()) {
+ PyErr_SetString(PyExc_RuntimeError,
+ "current thread state doesn't match GILState");
+ return NULL;
+ }
+
+ const char *err = NULL;
+ PyThreadState_Swap(NULL);
+ PyThreadState *substate = Py_NewInterpreter();
+
+ if (substate != PyThreadState_Get()) {
+ err = "subinterpreter thread state not current";
+ goto finally;
+ }
+ if (substate != PyGILState_GetThisThreadState()) {
+ err = "subinterpreter thread state doesn't match GILState";
+ goto finally;
+ }
+
+finally:
+ Py_EndInterpreter(substate);
+ PyThreadState_Swap(orig_tstate);
+
+ if (err != NULL) {
+ PyErr_SetString(PyExc_RuntimeError, err);
+ return NULL;
+ }
+ Py_RETURN_NONE;
+}
+
/* To run some code in a sub-interpreter. */
static PyObject *
run_in_subinterp(PyObject *self, PyObject *args)
@@ -3354,6 +3390,7 @@ static PyMethodDef TestMethods[] = {
{"make_memoryview_from_NULL_pointer", make_memoryview_from_NULL_pointer,
METH_NOARGS},
{"crash_no_current_thread", crash_no_current_thread, METH_NOARGS},
+ {"test_current_tstate_matches", test_current_tstate_matches, METH_NOARGS},
{"run_in_subinterp", run_in_subinterp, METH_VARARGS},
{"run_in_subinterp_with_config",
_PyCFunction_CAST(run_in_subinterp_with_config),