From 6bfbfd6edd0f9701664698768f9ec8d29f96a5bd Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Tue, 18 Sep 2018 10:57:47 +0200 Subject: Fix crash when garbage collecting in a non-GUI thread If a GUI class happens to be detected unreferenced when garbage collecting in a non-GUI thread and is subsequently deleted, crashes can occur for QWidgets and similar classes. The hitherto unimplemented delete-in-main-thread" attribute should be used. Add the missing implementation. Add the field to shiboken's type entry and SbkObjectTypePrivate class and pass it via newly introduced flags to introduceWrapperType(). Defer the deletion when invoked from the background thread and store the list of destructors in a list in binding manager run by Py_AddPendingCall(). Task-number: PYSIDE-743 Task-number: PYSIDE-810 Change-Id: Id4668a6a1e32392be9dcf1229e1e10c492b2a5f5 Reviewed-by: Qt CI Bot Reviewed-by: Cristian Maureira-Fredes Reviewed-by: Alexandru Croitor --- sources/shiboken2/ApiExtractor/abstractmetalang.cpp | 7 +++++++ sources/shiboken2/ApiExtractor/abstractmetalang.h | 2 ++ sources/shiboken2/ApiExtractor/typedatabase.cpp | 1 + sources/shiboken2/ApiExtractor/typesystem.cpp | 7 ++++--- sources/shiboken2/ApiExtractor/typesystem.h | 4 ++++ 5 files changed, 18 insertions(+), 3 deletions(-) (limited to 'sources/shiboken2/ApiExtractor') diff --git a/sources/shiboken2/ApiExtractor/abstractmetalang.cpp b/sources/shiboken2/ApiExtractor/abstractmetalang.cpp index 35e12f780..c65d7e0bd 100644 --- a/sources/shiboken2/ApiExtractor/abstractmetalang.cpp +++ b/sources/shiboken2/ApiExtractor/abstractmetalang.cpp @@ -1613,6 +1613,13 @@ void AbstractMetaClass::setTemplateBaseClassInstantiations(AbstractMetaTypeList& metaClassBaseTemplateInstantiations()->insert(this, instantiations); } +// Does any of the base classes require deletion in the main thread? +bool AbstractMetaClass::deleteInMainThread() const +{ + return typeEntry()->deleteInMainThread() + || (m_baseClass && m_baseClass->deleteInMainThread()); +} + static bool functions_contains(const AbstractMetaFunctionList &l, const AbstractMetaFunction *func) { for (const AbstractMetaFunction *f : l) { diff --git a/sources/shiboken2/ApiExtractor/abstractmetalang.h b/sources/shiboken2/ApiExtractor/abstractmetalang.h index 42129e9b7..aaefa32d5 100644 --- a/sources/shiboken2/ApiExtractor/abstractmetalang.h +++ b/sources/shiboken2/ApiExtractor/abstractmetalang.h @@ -1699,6 +1699,8 @@ public: return m_hasToStringCapability; } + bool deleteInMainThread() const; + static AbstractMetaClass *findClass(const AbstractMetaClassList &classes, const QString &name); static AbstractMetaClass *findClass(const AbstractMetaClassList &classes, diff --git a/sources/shiboken2/ApiExtractor/typedatabase.cpp b/sources/shiboken2/ApiExtractor/typedatabase.cpp index 69cddca4c..dcfd9f740 100644 --- a/sources/shiboken2/ApiExtractor/typedatabase.cpp +++ b/sources/shiboken2/ApiExtractor/typedatabase.cpp @@ -782,6 +782,7 @@ void ComplexTypeEntry::formatDebug(QDebug &d) const FORMAT_BOOL("QObject", m_qobject) FORMAT_BOOL("polymorphicBase", m_polymorphicBase) FORMAT_BOOL("genericClass", m_genericClass) + FORMAT_BOOL("deleteInMainThread", m_deleteInMainThread) if (m_typeFlags != 0) d << ", typeFlags=" << m_typeFlags; d << ", copyableFlag=" << m_copyableFlag diff --git a/sources/shiboken2/ApiExtractor/typesystem.cpp b/sources/shiboken2/ApiExtractor/typesystem.cpp index ba219cf5f..21c35bda6 100644 --- a/sources/shiboken2/ApiExtractor/typesystem.cpp +++ b/sources/shiboken2/ApiExtractor/typesystem.cpp @@ -1301,8 +1301,8 @@ void Handler::applyComplexTypeAttributes(const QXmlStreamReader &reader, if (convertBoolean(attributes->takeAt(i).value(), deprecatedAttribute(), false)) ctype->setTypeFlags(ctype->typeFlags() | ComplexTypeEntry::Deprecated); } else if (name == deleteInMainThreadAttribute()) { - qCWarning(lcShiboken, "%s", - qPrintable(msgUnimplementedAttributeWarning(reader, name))); + if (convertBoolean(attributes->takeAt(i).value(), deleteInMainThreadAttribute(), false)) + ctype->setDeleteInMainThread(true); } else if (name == QLatin1String("target-type")) { ctype->setTargetType(attributes->takeAt(i).value().toString()); } @@ -3221,7 +3221,8 @@ ComplexTypeEntry::ComplexTypeEntry(const QString &name, TypeEntry::Type t, m_qualifiedCppName(name), m_qobject(false), m_polymorphicBase(false), - m_genericClass(false) + m_genericClass(false), + m_deleteInMainThread(false) { } diff --git a/sources/shiboken2/ApiExtractor/typesystem.h b/sources/shiboken2/ApiExtractor/typesystem.h index 028f016f3..721d19f29 100644 --- a/sources/shiboken2/ApiExtractor/typesystem.h +++ b/sources/shiboken2/ApiExtractor/typesystem.h @@ -1346,6 +1346,9 @@ public: m_genericClass = isGeneric; } + bool deleteInMainThread() const { return m_deleteInMainThread; } + void setDeleteInMainThread(bool d) { m_deleteInMainThread = d; } + CopyableFlag copyable() const { return m_copyableFlag; @@ -1403,6 +1406,7 @@ private: uint m_qobject : 1; uint m_polymorphicBase : 1; uint m_genericClass : 1; + uint m_deleteInMainThread : 1; QString m_polymorphicIdValue; QString m_lookupName; -- cgit v1.2.3