diff options
author | Eric Snow <ericsnowcurrently@gmail.com> | 2023-02-06 22:53:31 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-02-06 22:53:31 (GMT) |
commit | 914f8fd9f7fc5e48b54d938a68c932cc618ef3a6 (patch) | |
tree | 77f87c6c45f28a9795116b89c6fd7f2e2dd13306 | |
parent | 38752760c91c87dd67af16d2cee611a22e647567 (diff) | |
download | cpython-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.py | 3 | ||||
-rw-r--r-- | Modules/_testcapimodule.c | 37 |
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), |