summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorFabian Kosmale <fabian.kosmale@qt.io>2020-06-11 19:37:19 +0200
committerFabian Kosmale <fabian.kosmale@qt.io>2020-06-25 14:11:56 +0200
commitc2fb27f054b228311fdba71f2a49cb09ae2a8fc8 (patch)
treed9929ac88630dd26d6a4ae89feead992a62b1fba /src
parent41ceb88fe1ecc1cdb8944d90aafff848c3c6f885 (diff)
Fix QProperty
This fixes two issues with QPropery: 1. QPropertyBindingPrivate::evaluateIfDirtyAndReturnTrueIfValueChanged calls a user provided evaluaton function. That one might actually destroy the binding and delete the QPropertyBindingPrivate instance. We need however to keep it alive until the function returns. 2. There was an infinite loop between QPropertyObserverPointer::notify and QPropertyBindingPrivate::markDirtyAndNotifyObservers. This can be observed when running tst_palette in qqc2. By returning early in markDirtyAndNotifyObservers if dirty is already set, the issue is avoided. Change-Id: I1f0df05a5a9fa98554183263a25e16747c4d2274 Reviewed-by: Ulf Hermann <ulf.hermann@qt.io> Reviewed-by: Simon Hausmann <hausmann@gmail.com>
Diffstat (limited to 'src')
-rw-r--r--src/corelib/kernel/qpropertybinding.cpp11
1 files changed, 11 insertions, 0 deletions
diff --git a/src/corelib/kernel/qpropertybinding.cpp b/src/corelib/kernel/qpropertybinding.cpp
index 9c46d63998..cbb9752e2e 100644
--- a/src/corelib/kernel/qpropertybinding.cpp
+++ b/src/corelib/kernel/qpropertybinding.cpp
@@ -64,6 +64,8 @@ void QPropertyBindingPrivate::unlinkAndDeref()
void QPropertyBindingPrivate::markDirtyAndNotifyObservers()
{
+ if (dirty)
+ return;
dirty = true;
if (firstObserver)
firstObserver.notify(this, propertyDataPtr);
@@ -81,6 +83,15 @@ bool QPropertyBindingPrivate::evaluateIfDirtyAndReturnTrueIfValueChanged()
return false;
}
+ /*
+ * Evaluating the binding might lead to the binding being broken. This can
+ * cause ref to reach zero at the end of the function. However, the
+ * updateGuard's destructor will then still trigger, trying to set the
+ * updating bool to its old value
+ * To prevent this, we create a QPropertyBindingPrivatePtr which ensures
+ * that the object is still alive when updateGuard's dtor runs.
+ */
+ QPropertyBindingPrivatePtr keepAlive {this};
QScopedValueRollback<bool> updateGuard(updating, true);
BindingEvaluationState evaluationFrame(this);