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>
This commit is contained in:
Fabian Kosmale 2020-06-11 19:37:19 +02:00
parent 41ceb88fe1
commit c2fb27f054

View File

@ -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);