Skip to content

Commit cb4e0f6

Browse files
WIP: Attempting to fix issue #75
This more explicitly handles the GIL; its possible some of our operations without GIL locking were invalid and only spotted during debug builds.
1 parent da8b793 commit cb4e0f6

1 file changed

Lines changed: 32 additions & 0 deletions

File tree

context/_coroutine.c

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,8 +81,25 @@ static void *coroutine_wrapper(void *action_, void *arg_)
8181

8282
/* New coroutine gets a brand new Python interpreter stack frame. */
8383
#if PY_VERSION_HEX >= 0x30B0000
84+
85+
PyGILState_STATE gstate;
86+
87+
88+
printf("wrapper before ThreadState_New GIL state: %d\n", PyGILState_Check());
89+
8490
PyThreadState *new_threadstate = PyThreadState_New(thread_state->interp);
91+
92+
93+
PyThreadState *eval_threadstate = PyEval_SaveThread();
94+
8595
thread_state = PyThreadState_Swap(new_threadstate);
96+
97+
gstate = PyGILState_Ensure();
98+
printf("wrapper after PyGILState_Ensure GIL state: %d\n", PyGILState_Check());
99+
100+
101+
102+
printf("wrapper after ThreadState_Swap GIL state: %d\n", PyGILState_Check());
86103
#else
87104
thread_state->frame = NULL;
88105
thread_state->recursion_depth = 0;
@@ -100,17 +117,29 @@ static void *coroutine_wrapper(void *action_, void *arg_)
100117
#endif
101118

102119
/* Call the given action with the passed argument. */
120+
121+
printf("wrapper before CallFunction GIL state: %d\n", PyGILState_Check());
122+
103123
PyObject *action = *(PyObject **)action_;
104124
PyObject *arg = arg_;
105125
PyObject *result = PyObject_CallFunctionObjArgs(action, arg, NULL);
106126
Py_DECREF(action);
107127
Py_DECREF(arg);
108128

129+
printf("wrapper after CallFunction GIL state: %d\n", PyGILState_Check());
130+
131+
132+
109133

110134
#if PY_VERSION_HEX >= 0x30B0000
111135
new_threadstate = PyThreadState_Swap(thread_state);
112136
PyThreadState_Clear(new_threadstate);
113137
PyThreadState_Delete(new_threadstate);
138+
139+
PyEval_RestoreThread(eval_threadstate);
140+
141+
PyGILState_Release(gstate);
142+
114143
#else
115144
/* Some of the stuff we've initialised can leak through, so far I've only
116145
* seen exc_type still set at this point, but maybe other fields can also
@@ -184,12 +213,15 @@ static PyObject *coroutine_switch(PyObject *Self, PyObject *args)
184213
#endif
185214
#endif
186215

216+
printf("switch before CallFunction GIL state: %d\n", PyGILState_Check());
187217
/* Switch to new coroutine. For the duration arg needs an extra
188218
* reference count, it'll be accounted for either on the next returned
189219
* result or in the entry to a new coroutine. */
190220
Py_INCREF(arg);
191221
PyObject *result = switch_cocore(target, arg);
192222

223+
printf("switch after CallFunction GIL state: %d\n", PyGILState_Check());
224+
193225
#if PY_VERSION_HEX >= 0x30B0000
194226
PyThreadState_Swap(thread_state);
195227
#else

0 commit comments

Comments
 (0)