diff options
author | Christian Tismer <tismer@stackless.com> | 2023-01-25 19:06:12 +0100 |
---|---|---|
committer | Christian Tismer <tismer@stackless.com> | 2023-02-02 09:29:00 +0100 |
commit | db40e3e07932576bc54cd922eecd423c0f675613 (patch) | |
tree | 28e9dec9e104dcefc4052fb67970b5ce7ca925d7 /sources/pyside6/libpyside/pysidesignal.cpp | |
parent | f799f1dd678cd17b59436a0c3a734135841eaa10 (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.cpp | 21 |
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. |