aboutsummaryrefslogtreecommitdiffstats
path: root/libpyside
diff options
context:
space:
mode:
authorFriedemann Kleint <Friedemann.Kleint@qt.io>2016-09-09 14:20:58 +0200
committerFriedemann Kleint <Friedemann.Kleint@qt.io>2016-09-19 13:28:40 +0000
commit3eb940cbd77cea9603d1c180f81eb4a2a474ef90 (patch)
treef55089f306993cbe82d2a9eefd3751fbd2b57a0a /libpyside
parent7ed4c11de3bded1bfb67cddaade2da518559527a (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.cpp22
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;