Damien LEFEVRE added the comment:
I see the same problem.
We call python functions from C++ and use this locking class within each call:
'''
#pragma once
#ifdef _DEBUG
#undef _DEBUG
#include
#define _DEBUG
#else
#include
#endif // _DEBUG
#include "gcc_helper.h"
GCC_DIAG_OFF(maybe-uninitialized)
class GIL_lock
{
public:
GIL_lock()
{
m_wasPreviouslyLockedByThisThread = PyGILState_Check() == 1;
// If already locked, we shouldn't lock again.
if (m_wasPreviouslyLockedByThisThread == false)
{
m_state = PyGILState_Ensure();
}
}
~GIL_lock()
{
release();
}
void release()
{
// Release only if it wasn't locked previously and wasn't released
during lifetime.
if (m_released == false && m_wasPreviouslyLockedByThisThread == false)
{
PyGILState_Release(m_state);
}
m_released = true;
}
private:
PyGILState_STATE m_state;
bool m_released = false;
bool m_wasPreviouslyLockedByThisThread = false;
};
'''
Example:
'''
void PythonInterpreterPrivate::setPythonHome(const QString& path)
{
GIL_lock gilLock;
#ifdef _WIN32
wchar_t* pyHome = new wchar_t[MAX_PATH];
#else
wchar_t* pyHome = new wchar_t[PATH_MAX];
#endif
QDir pythonDir(path);
if (pythonDir.exists())
{
path.toWCharArray(pyHome);
pyHome[path.size()] = 0;
Py_SetPythonHome(pyHome);
}
}
'''
With Python3.6, the first instance of GIL_lock in the main thread goes to
PyGILState_Ensure(). With Python3.7, still in the main thread
PyGILState_Check() reports the lock is already taken while we don't take it.
In a new thread, with Python3.7 GIL_lock() goes to PyGILState_Ensure() and
deadlocks there. With Python3.6 PyGILState_Ensure() returns the state.
--
nosy: +Damien LEFEVRE
___
Python tracker
<https://bugs.python.org/issue38680>
___
___
Python-bugs-list mailing list
Unsubscribe:
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com