I had exactly the same problem and it is now solved by using PyEval_SaveThread()
immediately after PyEval_InitThreads()
, as you suggest above. However, my actual problem was that I used PyEval_InitThreads()
after PyInitialise()
which then caused PyGILState_Ensure()
to block when called from different, subsequent native threads. In summary, this is what I do now:
-
There is global variable:
static int gil_init = 0;
-
From a main thread load the native C extension and start the Python interpreter:
Py_Initialize()
-
From multiple other threads my app concurrently makes a lot of calls into the Python/C API:
if (!gil_init) { gil_init = 1; PyEval_InitThreads(); PyEval_SaveThread(); } state = PyGILState_Ensure(); // Call Python/C API functions... PyGILState_Release(state);
-
From the main thread stop the Python interpreter
Py_Finalize()
All other solutions I’ve tried either caused random Python sigfaults or deadlock/blocking using PyGILState_Ensure()
.
The Python documentation really should be more clear on this and at least provide an example for both the embedding and extension use cases.