diff options
| author | Friedemann Kleint <Friedemann.Kleint@qt.io> | 2023-06-26 11:02:56 +0200 |
|---|---|---|
| committer | Friedemann Kleint <Friedemann.Kleint@qt.io> | 2023-06-28 08:25:11 +0200 |
| commit | 46ab90a5f9493ba0687834e6fa83413ca2437ce5 (patch) | |
| tree | 44c9199067dced397b8ec1534dcf3513678b42b1 /sources/pyside6/libpyside/signalmanager.cpp | |
| parent | 0c582b55984c5aa2490e807b9cf6010656fa10d5 (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.cpp | 19 |
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); |
