@@ -89,16 +89,33 @@ def test_register_new_thread(self):
89
89
includes = "#include <pthread.h>" ,
90
90
code = r'''
91
91
void* thread_entrypoint(void* arg) {
92
+ // This check is important not just to check that the function works without the thread attached,
93
+ // but also because the thread attaching logic in it can break the following PyGILState_Ensure call
94
+ if (PyGILState_Check()) {
95
+ PyErr_SetString(PyExc_RuntimeError, "Thread shouldn't be holding the GIL at this point");
96
+ PyErr_WriteUnraisable(NULL);
97
+ return NULL;
98
+ }
92
99
PyObject* callable = (PyObject*)arg;
93
100
PyGILState_STATE gstate;
94
101
gstate = PyGILState_Ensure();
102
+ if (!PyGILState_Check()) {
103
+ PyErr_SetString(PyExc_RuntimeError, "GIL not acquired");
104
+ PyErr_WriteUnraisable(NULL);
105
+ return NULL;
106
+ }
95
107
if (!PyObject_CallNoArgs(callable)) {
96
108
PyErr_WriteUnraisable(callable);
97
109
}
98
110
if (PyThreadState_Get() == NULL || PyThreadState_Get() == NULL) {
99
111
PyErr_WriteUnraisable(callable);
100
112
}
101
113
PyGILState_Release(gstate);
114
+ if (PyGILState_Check()) {
115
+ PyErr_SetString(PyExc_RuntimeError, "GIL not released");
116
+ PyErr_WriteUnraisable(NULL);
117
+ return NULL;
118
+ }
102
119
return NULL;
103
120
}
104
121
PyObject* run_in_thread(PyObject* self, PyObject* callable) {
0 commit comments