aboutsummaryrefslogtreecommitdiffstats
path: root/sources/pyside6/libpyside/signalmanager.cpp
diff options
context:
space:
mode:
authorFriedemann Kleint <Friedemann.Kleint@qt.io>2023-06-26 11:02:56 +0200
committerFriedemann Kleint <Friedemann.Kleint@qt.io>2023-06-28 08:25:11 +0200
commit46ab90a5f9493ba0687834e6fa83413ca2437ce5 (patch)
tree44c9199067dced397b8ec1534dcf3513678b42b1 /sources/pyside6/libpyside/signalmanager.cpp
parent0c582b55984c5aa2490e807b9cf6010656fa10d5 (diff)
PySide6/SignalManager: Fix memory leaks connecting free methods/lambdas
Change 1270a9e82e5bc3bd53a1131698ece60403da1192 changed the deletion of global receivers from listening to QObject::destroyed() (which caused thread issues) to using QPointer<> and purging the lists in notify. What is missing was the deletion of global receivers that are not tied by weak reference to a Python instance. Add a check in notify() to clean out the empty global receivers. Pick-to: 6.5 Fixes: PYSIDE-2371 Fixes: PYSIDE-2299 Task-number: PYSIDE-2141 Change-Id: I39dca2a21088930c9a7f8e5eb7e948b3fff49b4b Reviewed-by: Christian Tismer <tismer@stackless.com> Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Diffstat (limited to 'sources/pyside6/libpyside/signalmanager.cpp')
-rw-r--r--sources/pyside6/libpyside/signalmanager.cpp19
1 files changed, 19 insertions, 0 deletions
diff --git a/sources/pyside6/libpyside/signalmanager.cpp b/sources/pyside6/libpyside/signalmanager.cpp
index 753b50557..aa20c23d6 100644
--- a/sources/pyside6/libpyside/signalmanager.cpp
+++ b/sources/pyside6/libpyside/signalmanager.cpp
@@ -210,6 +210,7 @@ struct SignalManager::SignalManagerPrivate
void deleteGobalReceiver(const QObject *gr);
void clear();
+ void purgeEmptyGobalReceivers();
GlobalReceiverV2Map m_globalReceivers;
static SignalManager::QmlMetaCallErrorHandler m_qmlMetaCallErrorHandler;
@@ -307,6 +308,7 @@ QObject *SignalManager::globalReceiver(QObject *sender, PyObject *callback, QObj
void SignalManager::notifyGlobalReceiver(QObject *receiver)
{
reinterpret_cast<GlobalReceiverV2 *>(receiver)->notify();
+ m_d->purgeEmptyGobalReceivers();
}
void SignalManager::releaseGlobalReceiver(const QObject *source, QObject *receiver)
@@ -342,6 +344,23 @@ void SignalManager::SignalManagerPrivate::clear()
m_globalReceivers.erase(m_globalReceivers.cbegin());
}
+static bool isEmptyGlobalReceiver(const GlobalReceiverV2Ptr &g)
+{
+ return g->isEmpty();
+}
+
+void SignalManager::SignalManagerPrivate::purgeEmptyGobalReceivers()
+{
+ // Delete repetitively (see comment in clear()).
+ while (true) {
+ auto it = std::find_if(m_globalReceivers.cbegin(), m_globalReceivers.cend(),
+ isEmptyGlobalReceiver);
+ if (it == m_globalReceivers.cend())
+ break;
+ m_globalReceivers.erase(it);
+ }
+}
+
int SignalManager::globalReceiverSlotIndex(QObject *receiver, const char *signature) const
{
return static_cast<GlobalReceiverV2 *>(receiver)->addSlot(signature);