From 05b7251797fa66df6af73c01901c7ef86b2733bf Mon Sep 17 00:00:00 2001 From: Julien Wadel Date: Mon, 20 Jan 2025 10:36:27 +0100 Subject: [PATCH] Fix async crashes like getting display name from Ui. --- Linphone/model/object/SafeObject.hpp | 1 + Linphone/model/object/VariantObject.cpp | 37 ++++++++++++++++--------- Linphone/model/object/VariantObject.hpp | 13 ++++++--- 3 files changed, 34 insertions(+), 17 deletions(-) diff --git a/Linphone/model/object/SafeObject.hpp b/Linphone/model/object/SafeObject.hpp index 1a4c0a505..594ffb519 100644 --- a/Linphone/model/object/SafeObject.hpp +++ b/Linphone/model/object/SafeObject.hpp @@ -36,6 +36,7 @@ public: QVariant getValue() const; void onSetValue(QVariant value); void setDefaultValue(QVariant value); // Don't send signal + bool mDeleted = false; signals: void requestValue(); void setValue(QVariant value); diff --git a/Linphone/model/object/VariantObject.cpp b/Linphone/model/object/VariantObject.cpp index 51b8c9690..df98316ad 100644 --- a/Linphone/model/object/VariantObject.cpp +++ b/Linphone/model/object/VariantObject.cpp @@ -40,24 +40,35 @@ VariantObject::VariantObject(QString name, QVariant defaultValue, QObject *paren mConnection = QSharedPointer>( new SafeConnection(mCoreObject, mModelObject), &QObject::deleteLater); - mConnection->makeConnectToCore(&SafeObject::setValue, [this, d = mName](QVariant value) { - mConnection->invokeToModel([this, value, d]() { - if (mModelObject) mModelObject->onSetValue(value); - }); - }); - mConnection->makeConnectToModel(&SafeObject::setValue, [this, d = mName, coreObject = mCoreObject](QVariant value) { - // Note: do not use member because 'this' is managed by GUI and can be deleted. - mConnection->invokeToCore([this, d, coreObject, value]() { - if (coreObject) coreObject->onSetValue(value); - }); - }); - mConnection->makeConnectToModel(&SafeObject::valueChanged, [this](QVariant value) { - mConnection->invokeToCore([this, value]() { mCoreObject->valueChanged(value); }); + // Note: do not use member because 'this' is managed by GUI and can be deleted. Objects scope should have the same + // as connections so it should be fine to use the object directly. + mConnection->makeConnectToCore(&SafeObject::setValue, + [this, d = mName, modelObject = mModelObject.get()](QVariant value) { + if (modelObject && !modelObject->mDeleted) + mConnection->invokeToModel([this, value, d, modelObject]() { + if (modelObject && !modelObject->mDeleted) + modelObject->onSetValue(value); + }); + }); + mConnection->makeConnectToModel(&SafeObject::setValue, + [this, d = mName, coreObject = mCoreObject.get()](QVariant value) { + if (coreObject && !coreObject->mDeleted) + mConnection->invokeToCore([this, d, coreObject, value]() { + if (coreObject && !coreObject->mDeleted) coreObject->onSetValue(value); + }); + }); + mConnection->makeConnectToModel(&SafeObject::valueChanged, [this, coreObject = mCoreObject.get()](QVariant value) { + if (coreObject && !coreObject->mDeleted) + mConnection->invokeToCore([this, value, coreObject]() { + if (coreObject && !coreObject->mDeleted) coreObject->valueChanged(value); + }); }); connect(mCoreObject.get(), &SafeObject::valueChanged, this, &VariantObject::valueChanged); } VariantObject::~VariantObject() { + mCoreObject->mDeleted = true; + mModelObject->mDeleted = true; } QVariant VariantObject::getValue() const { diff --git a/Linphone/model/object/VariantObject.hpp b/Linphone/model/object/VariantObject.hpp index 6ae2f9a54..afc51e944 100644 --- a/Linphone/model/object/VariantObject.hpp +++ b/Linphone/model/object/VariantObject.hpp @@ -38,13 +38,18 @@ class VariantObject : public QObject, public AbstractObject { public: VariantObject(QString name, QObject *parent = nullptr); VariantObject(QString name, QVariant defaultValue, QObject *parent = nullptr); - ~VariantObject(); + virtual ~VariantObject(); + // Note: do not use member because 'this' is managed by GUI and can be deleted. Objects scope should have the same + // as connections so it should be fine to use the object directly. template void makeRequest(Func &&callable, Args &&...args) { - mConnection->makeConnectToCore(&SafeObject::requestValue, [this, callable, args...]() { - mConnection->invokeToModel([this, callable, args...]() { mModelObject->setValue(callable(args...)); }); - }); + mConnection->makeConnectToCore(&SafeObject::requestValue, + [this, modelObject = mModelObject.get(), callable, args...]() { + mConnection->invokeToModel([this, modelObject, callable, args...]() { + modelObject->setValue(callable(args...)); + }); + }); } template void makeUpdate(Sender sender, SenderClass signal) {