diff options
author | Friedemann Kleint <Friedemann.Kleint@qt.io> | 2016-09-09 14:20:58 +0200 |
---|---|---|
committer | Friedemann Kleint <Friedemann.Kleint@qt.io> | 2016-09-19 13:28:40 +0000 |
commit | 3eb940cbd77cea9603d1c180f81eb4a2a474ef90 (patch) | |
tree | f55089f306993cbe82d2a9eefd3751fbd2b57a0a /libpyside | |
parent | 7ed4c11de3bded1bfb67cddaade2da518559527a (diff) |
GlobalReceiverV2: Suppress handling of destroyed() when deleting objects
Set the dynamic slot member m_data to 0 before deleting it and bail
out of qt_metacall() if that is the case.
This prevents a crash when the object is deleted by this if the last
reference was held by it.
Task-number: PYSIDE-88
Change-Id: Iaf173f1305c92861425af2c6447a6aab99451634
Reviewed-by: Alexandru Croitor <alexandru.croitor@qt.io>
Diffstat (limited to 'libpyside')
-rw-r--r-- | libpyside/globalreceiverv2.cpp | 22 |
1 files changed, 20 insertions, 2 deletions
diff --git a/libpyside/globalreceiverv2.cpp b/libpyside/globalreceiverv2.cpp index d7033be4..b25b04c5 100644 --- a/libpyside/globalreceiverv2.cpp +++ b/libpyside/globalreceiverv2.cpp @@ -194,9 +194,18 @@ GlobalReceiverV2::GlobalReceiverV2(PyObject *callback, SharedMap map) GlobalReceiverV2::~GlobalReceiverV2() { m_refs.clear(); - //Remove itself from map + // Remove itself from map. m_sharedMap->remove(m_data->hash()); - delete m_data; + // Suppress handling of destroyed() for objects whose last reference is contained inside + // the callback object that will now be deleted. The reference could be a default argument, + // a callback local variable, etc. + // The signal has to be suppressed because it would lead to the following situation: + // Callback is deleted, hence the last reference is decremented, + // leading to the object being deleted, which emits destroyed(), which would try to invoke + // the already deleted callback, and also try to delete the object again. + DynamicSlotDataV2 *data = m_data; + m_data = Q_NULLPTR; + delete data; } int GlobalReceiverV2::addSlot(const char* signature) @@ -293,6 +302,15 @@ int GlobalReceiverV2::qt_metacall(QMetaObject::Call call, int id, void** args) QMetaMethod slot = metaObject()->method(id); Q_ASSERT(slot.methodType() == QMetaMethod::Slot); + if (!m_data) { + if (id != DESTROY_SLOT_ID) { + const QByteArray message = "PySide2 Warning: Skipping callback call " + + slot.methodSignature() + " because the callback object is being destructed."; + PyErr_WarnEx(PyExc_RuntimeWarning, message.constData(), 0); + } + return -1; + } + if (id == DESTROY_SLOT_ID) { if (m_refs.size() == 0) return -1; |