Message 32027 - Python tracker (original) (raw)

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