diff options
author | Fabian Kosmale <fabian.kosmale@qt.io> | 2020-06-11 19:37:19 +0200 |
---|---|---|
committer | Fabian Kosmale <fabian.kosmale@qt.io> | 2020-06-25 14:11:56 +0200 |
commit | c2fb27f054b228311fdba71f2a49cb09ae2a8fc8 (patch) | |
tree | d9929ac88630dd26d6a4ae89feead992a62b1fba | |
parent | 41ceb88fe1ecc1cdb8944d90aafff848c3c6f885 (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>
-rw-r--r-- | src/corelib/kernel/qpropertybinding.cpp | 11 |
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); |