diff options
Diffstat (limited to 'sources/pyside2/libpyside/signalmanager.cpp')
-rw-r--r-- | sources/pyside2/libpyside/signalmanager.cpp | 29 |
1 files changed, 27 insertions, 2 deletions
diff --git a/sources/pyside2/libpyside/signalmanager.cpp b/sources/pyside2/libpyside/signalmanager.cpp index c21a3e565..93847e066 100644 --- a/sources/pyside2/libpyside/signalmanager.cpp +++ b/sources/pyside2/libpyside/signalmanager.cpp @@ -114,18 +114,24 @@ namespace PySide { PyObjectWrapper::PyObjectWrapper() :m_me(Py_None) { + // PYSIDE-813: When PYSIDE-164 was solved by adding some thread allowance, + // this code was no longer protected. It was hard to find this connection. + // See the website https://bugreports.qt.io/browse/PYSIDE-813 for details. + Shiboken::GilState gil; Py_XINCREF(m_me); } PyObjectWrapper::PyObjectWrapper(PyObject *me) : m_me(me) { + Shiboken::GilState gil; Py_XINCREF(m_me); } PyObjectWrapper::PyObjectWrapper(const PyObjectWrapper &other) : m_me(other.m_me) { + Shiboken::GilState gil; Py_XINCREF(m_me); } @@ -142,6 +148,7 @@ PyObjectWrapper::~PyObjectWrapper() void PyObjectWrapper::reset(PyObject *o) { + Shiboken::GilState gil; Py_XINCREF(o); Py_XDECREF(m_me); m_me = o; @@ -404,11 +411,13 @@ int SignalManager::qt_metacall(QObject *object, QMetaObject::Call call, int id, case QMetaObject::ReadProperty: case QMetaObject::WriteProperty: case QMetaObject::ResetProperty: +# if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) case QMetaObject::QueryPropertyDesignable: case QMetaObject::QueryPropertyScriptable: case QMetaObject::QueryPropertyStored: case QMetaObject::QueryPropertyEditable: case QMetaObject::QueryPropertyUser: +# endif // < Qt 6 pp->d->metaCallHandler(pp, pySelf, call, args); break; #endif @@ -550,10 +559,19 @@ bool SignalManager::registerMetaMethod(QObject *source, const char *signature, Q static MetaObjectBuilder *metaBuilderFromDict(PyObject *dict) { + // PYSIDE-803: The dict in this function is the ob_dict of an SbkObject. + // The "metaObjectAttr" entry is only handled in this file. There is no + // way in this function to involve the interpreter. Therefore, we need + // no GIL. + // Note that "SignalManager::registerMetaMethodGetIndex" has write actions + // that might involve the interpreter, but in that context the GIL is held. if (!dict || !PyDict_Contains(dict, metaObjectAttr)) return nullptr; - PyObject *pyBuilder = PyDict_GetItem(dict, metaObjectAttr); + // PYSIDE-813: The above assumption is not true in debug mode: + // PyDict_GetItem would touch PyThreadState_GET and the global error state. + // PyDict_GetItemWithError instead can work without GIL. + PyObject *pyBuilder = PyDict_GetItemWithError(dict, metaObjectAttr); #ifdef IS_PY3K return reinterpret_cast<MetaObjectBuilder *>(PyCapsule_GetPointer(pyBuilder, nullptr)); #else @@ -605,7 +623,14 @@ int SignalManager::registerMetaMethodGetIndex(QObject *source, const char *signa const QMetaObject *SignalManager::retrieveMetaObject(PyObject *self) { - Shiboken::GilState gil; + // PYSIDE-803: Avoid the GIL in SignalManager::retrieveMetaObject + // This function had the GIL. We do not use the GIL unless we have to. + // metaBuilderFromDict accesses a Python dict, but in that context there + // is no way to reach the interpreter, see "metaBuilderFromDict". + // + // The update function is MetaObjectBuilderPrivate::update in + // dynamicmetaobject.c . That function now uses the GIL when the + // m_dirty flag is set. Q_ASSERT(self); MetaObjectBuilder *builder = metaBuilderFromDict(reinterpret_cast<SbkObject *>(self)->ob_dict); |