Skip to content

Commit be35b2c

Browse files
committed
Fix GIL check to verify thread state before Py_BEGIN_ALLOW_THREADS
PyGILState_Check() can return true even with NULL thread state on some platforms. Add PyGILState_GetThisThreadState() check to ensure valid thread state before using Py_BEGIN_ALLOW_THREADS macro.
1 parent 43ea6b0 commit be35b2c

1 file changed

Lines changed: 7 additions & 6 deletions

File tree

c_src/py_event_loop.c

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -767,17 +767,18 @@ ERL_NIF_TERM nif_poll_events(ErlNifEnv *env, int argc,
767767
int num_events = 0;
768768

769769
/*
770-
* Check if we have the GIL before trying to release it.
771-
* If called from Erlang (not Python), we don't have the GIL.
772-
* PyGILState_Check returns 1 if current thread holds GIL, 0 otherwise.
770+
* Check if we have a valid Python thread state AND the GIL before releasing it.
771+
* PyGILState_Check() can return true even with NULL thread state on some platforms.
772+
* PyGILState_GetThisThreadState() returns NULL if thread has no Python state.
773773
*/
774-
if (g_python_initialized && PyGILState_Check()) {
775-
/* We have the GIL - release it while waiting */
774+
PyThreadState *tstate = PyGILState_GetThisThreadState();
775+
if (tstate != NULL && g_python_initialized && PyGILState_Check()) {
776+
/* We have valid thread state and GIL - release it while waiting */
776777
Py_BEGIN_ALLOW_THREADS
777778
num_events = poll_events_wait(loop, timeout_ms);
778779
Py_END_ALLOW_THREADS
779780
} else {
780-
/* No GIL - just wait directly */
781+
/* No GIL or invalid thread state - just wait directly */
781782
num_events = poll_events_wait(loop, timeout_ms);
782783
}
783784

0 commit comments

Comments
 (0)