]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-59956: Add a Test to Verify GILState Matches the "Current" Thread State (gh-101625)
authorEric Snow <ericsnowcurrently@gmail.com>
Mon, 6 Feb 2023 22:53:31 +0000 (15:53 -0700)
committerGitHub <noreply@github.com>
Mon, 6 Feb 2023 22:53:31 +0000 (15:53 -0700)
This test should have been in gh-101431.

https://github.com/python/cpython/issues/59956

Lib/test/test_capi/test_misc.py
Modules/_testcapimodule.c

index dace37c362e569f0069e852b248cc9fadfee7f51..03e22d7a2d382d1e4ea5d3ea890b6c7e4f11e3fb 100644 (file)
@@ -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))
index f0d6e404f54a2f1a020e4fb9a0251680e852391c..5e47f4975a2d54d9c4a10528a5988f8f07b57150 100644 (file)
@@ -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),