@@ -1534,6 +1534,42 @@ crash_no_current_thread(PyObject *self, PyObject *Py_UNUSED(ignored))
1534
1534
return NULL ;
1535
1535
}
1536
1536
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
+
1537
1573
/* To run some code in a sub-interpreter. */
1538
1574
static PyObject *
1539
1575
run_in_subinterp (PyObject * self , PyObject * args )
@@ -3354,6 +3390,7 @@ static PyMethodDef TestMethods[] = {
3354
3390
{"make_memoryview_from_NULL_pointer" , make_memoryview_from_NULL_pointer ,
3355
3391
METH_NOARGS },
3356
3392
{"crash_no_current_thread" , crash_no_current_thread , METH_NOARGS },
3393
+ {"test_current_tstate_matches" , test_current_tstate_matches , METH_NOARGS },
3357
3394
{"run_in_subinterp" , run_in_subinterp , METH_VARARGS },
3358
3395
{"run_in_subinterp_with_config" ,
3359
3396
_PyCFunction_CAST (run_in_subinterp_with_config ),
0 commit comments