The function PyGILState_Ensure doesn't acquire the GIL if current thread state is valid. In contrast to that PyGILState_Release deletes the thread state (PyThreadState_DeleteCurrent) which releases the GIL which got not acquired before (=> mutex->owned = -2). Here is an example which locks at PyRun_SimpleString: // initialize the Python interpreter Py_Initialize(); PyEval_InitThreads(); // release the GIL as PyEval_InitThreads // implicitly acquires the GIL PyEval_ReleaseLock(); PyGILState_STATE gstate; gstate = PyGILState_Ensure(); PyRun_SimpleString("import random\n"); PyGILState_Release(gstate); In that simple example the problem can be fixed by removing the call to PyEval_ReleaseLock. But that is needed for applications that call into the interpreter from multiple threads. The only solution I could found up to that point is the following: // initialize the Python interpreter Py_Initialize(); PyEval_InitThreads(); PyThreadState* tcur = PyThreadState_Get() ; PyThreadState_Swap(NULL); PyThreadState_Clear(tcur); PyThreadState_Delete(tcur); // release the GIL as PyEval_InitThreads // implicitly acquires the GIL PyEval_ReleaseLock(); PyGILState_STATE gstate; gstate = PyGILState_Ensure(); PyRun_SimpleString("import random\n"); PyGILState_Release(gstate); Which seems to works fine. But I think that this behavior of PyGILState_Ensure should be either documented or fixed. Thanks, Kuno
In my embedding, I use the following (adapting the example above): // initialize the Python interpreter Py_Initialize(); PyEval_InitThreads(); /* Swap out and return current thread state and release the GIL */ PyThreadState tstate = PyEval_SaveThread(); PyGILState_STATE gstate; gstate = PyGILState_Ensure(); PyRun_SimpleString("import random\n"); PyGILState_Release(gstate); You don't have to free the tstate returned by PyEval_SaveThread because it is the thread state of the main thread (as established during Py_Initialize), and so it will be freed during Python's shut-down. I think in general you should rarely need to call PyEval_ReleaseLock directly; instead use PyEval_SaveThread, the Py_BEGIN_ALLOW_THREADS macro, or PyGILState_Release (as appropriate). The documentation should probably say as much.
This is still the case: the documentation should mention that PyEval_ReleaseLock() is not the correct function to release "the GIL", both the interpreter lock *and* the current thread state have to be released.