Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristian Tismer <tismer@stackless.com>2023-01-25 19:06:12 +0100
committerChristian Tismer <tismer@stackless.com>2023-02-02 09:29:00 +0100
commitdb40e3e07932576bc54cd922eecd423c0f675613 (patch)
tree28e9dec9e104dcefc4052fb67970b5ce7ca925d7 /sources/pyside6/libpyside/pysidesignal.cpp
parentf799f1dd678cd17b59436a0c3a734135841eaa10 (diff)
signals: Introduce Weak Reference to protect lost SignalInstance
This first solution detects the vanishing object and raises an exception. Trying to revive the object was unsuccessful. Since this happens only when no signals are connected, it is ok to leave it this way. Change-Id: Ib47f85657363b675cec3616b5550ce41d93fb4d3 Fixes: PYSIDE-2201 Pick-to: 6.4 Task-number: PYSIDE-79 Task-number: PYSIDE-68 Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org> Reviewed-by: Friedemann Kleint <Friedemann.Kleint@qt.io>
Diffstat (limited to 'sources/pyside6/libpyside/pysidesignal.cpp')
-rw-r--r--sources/pyside6/libpyside/pysidesignal.cpp21
1 files changed, 21 insertions, 0 deletions
diff --git a/sources/pyside6/libpyside/pysidesignal.cpp b/sources/pyside6/libpyside/pysidesignal.cpp
index 5df42261c..cdc3042c0 100644
--- a/sources/pyside6/libpyside/pysidesignal.cpp
+++ b/sources/pyside6/libpyside/pysidesignal.cpp
@@ -6,6 +6,7 @@
#include "pysidesignal_p.h"
#include "pysideutils.h"
#include "pysidestaticstrings.h"
+#include "pysideweakref.h"
#include "signalmanager.h"
#include <shiboken.h>
@@ -342,6 +343,7 @@ static void signalInstanceFree(void *vself)
}
delete dataPvt;
self->d = nullptr;
+ self->deleted = true;
Py_TYPE(pySelf)->tp_base->tp_free(self);
}
@@ -550,6 +552,13 @@ static PyObject *signalInstanceEmit(PyObject *self, PyObject *args)
{
PySideSignalInstance *source = reinterpret_cast<PySideSignalInstance *>(self);
+ // PYSIDE-2201: Check if the object has vanished meanwhile.
+ // Tried to revive it without exception, but this gives problems.
+ if (source->deleted) {
+ PyErr_Format(PyExc_RuntimeError, "The SignalInstance object was already deleted");
+ return nullptr;
+ }
+
Shiboken::AutoDecRef pyArgs(PyList_New(0));
int numArgsGiven = PySequence_Fast_GET_SIZE(args);
int numArgsInSignature = argCountInSignature(source->d->signature);
@@ -932,9 +941,16 @@ static void appendSignature(PySideSignal *self, const SignalSignature &signature
self->data->signatures.append({signature.m_parameterTypes, signature.m_attributes});
}
+static void sourceGone(void *data)
+{
+ auto *self = reinterpret_cast<PySideSignalInstance *>(data);
+ self->deleted = true;
+}
+
static void instanceInitialize(PySideSignalInstance *self, PyObject *name, PySideSignal *signal, PyObject *source, int index)
{
self->d = new PySideSignalInstancePrivate;
+ self->deleted = false;
PySideSignalInstancePrivate *selfPvt = self->d;
selfPvt->next = nullptr;
if (signal->data->signalName.isEmpty())
@@ -950,6 +966,10 @@ static void instanceInitialize(PySideSignalInstance *self, PyObject *name, PySid
selfPvt->homonymousMethod = signal->homonymousMethod;
Py_INCREF(selfPvt->homonymousMethod);
}
+ // PYSIDE-2201: We have no reference to source. Let's take a weakref to get
+ // notified when source gets deleted.
+ PySide::WeakRef::create(source, sourceGone, self);
+
index++;
if (index < signal->data->signatures.size()) {
@@ -1009,6 +1029,7 @@ PySideSignalInstance *newObjectFromMethod(PyObject *source, const QList<QMetaMet
previous->d->next = item;
item->d = new PySideSignalInstancePrivate;
+ item->deleted = false;
PySideSignalInstancePrivate *selfPvt = item->d;
selfPvt->source = source;
Py_INCREF(selfPvt->source); // PYSIDE-79: an INCREF is missing.