From 3456b4eb249d49239ec3cf822db950b8e20bb789 Mon Sep 17 00:00:00 2001 From: J-P Nurmi Date: Tue, 5 Jan 2016 10:19:19 +0100 Subject: Busy animators: fix access to childContainerNode() Accessing QQuickItemPrivate::childContainerNode() in updateCurrentTime(), which is executed in render thread context, is not safe and may cause random crashes. Change-Id: Ibbdf387f7e8d593740452e56b819a6d7fd9341e6 Reviewed-by: Mitch Curtis --- .../material/qquickmaterialprogressring.cpp | 20 ++++++++++++------ src/imports/controls/qquickbusyindicatorring.cpp | 24 ++++++++++++++++++---- 2 files changed, 34 insertions(+), 10 deletions(-) (limited to 'src') diff --git a/src/imports/controls/material/qquickmaterialprogressring.cpp b/src/imports/controls/material/qquickmaterialprogressring.cpp index 7f7ed114..54728686 100644 --- a/src/imports/controls/material/qquickmaterialprogressring.cpp +++ b/src/imports/controls/material/qquickmaterialprogressring.cpp @@ -71,9 +71,10 @@ public: void updateCurrentTime(int time) Q_DECL_OVERRIDE; void writeBack() Q_DECL_OVERRIDE; void nodeWasDestroyed() Q_DECL_OVERRIDE; + void afterNodeSync() Q_DECL_OVERRIDE; private: - QSGNode *m_itemNode; + QSGNode *m_containerNode; QQuickWindow *m_window; }; @@ -164,7 +165,7 @@ QQuickAnimatorJob *QQuickMaterialRingAnimator::createJob() const } QQuickMaterialRingAnimatorJob::QQuickMaterialRingAnimatorJob() : - m_itemNode(Q_NULLPTR), + m_containerNode(Q_NULLPTR), m_window(Q_NULLPTR) { } @@ -176,14 +177,16 @@ QQuickMaterialRingAnimatorJob::~QQuickMaterialRingAnimatorJob() void QQuickMaterialRingAnimatorJob::initialize(QQuickAnimatorController *controller) { QQuickAnimatorJob::initialize(controller); - m_itemNode = QQuickItemPrivate::get(m_target)->itemNode(); + m_containerNode = QQuickItemPrivate::get(m_target)->childContainerNode(); m_window = m_target->window(); } void QQuickMaterialRingAnimatorJob::updateCurrentTime(int time) { - QSGNode *childContainerNode = QQuickItemPrivate::get(m_target)->childContainerNode(); - QSGSimpleRectNode *rectNode = static_cast(childContainerNode->firstChild()); + if (!m_containerNode) + return; + + QSGSimpleRectNode *rectNode = static_cast(m_containerNode->firstChild()); if (!rectNode) return; @@ -252,10 +255,15 @@ void QQuickMaterialRingAnimatorJob::writeBack() void QQuickMaterialRingAnimatorJob::nodeWasDestroyed() { - m_itemNode = Q_NULLPTR; + m_containerNode = Q_NULLPTR; m_window = Q_NULLPTR; } +void QQuickMaterialRingAnimatorJob::afterNodeSync() +{ + m_containerNode = QQuickItemPrivate::get(m_target)->childContainerNode(); +} + QQuickMaterialRingTexture::QQuickMaterialRingTexture() { } diff --git a/src/imports/controls/qquickbusyindicatorring.cpp b/src/imports/controls/qquickbusyindicatorring.cpp index 4711ae1b..18413b73 100644 --- a/src/imports/controls/qquickbusyindicatorring.cpp +++ b/src/imports/controls/qquickbusyindicatorring.cpp @@ -50,9 +50,14 @@ public: QQuickBusyIndicatorAnimatorJob(); ~QQuickBusyIndicatorAnimatorJob(); + void initialize(QQuickAnimatorController *controller) Q_DECL_OVERRIDE; void updateCurrentTime(int time) Q_DECL_OVERRIDE; void writeBack() Q_DECL_OVERRIDE; void nodeWasDestroyed() Q_DECL_OVERRIDE; + void afterNodeSync() Q_DECL_OVERRIDE; + +private: + QSGNode *m_node; }; static const int circles = 10; @@ -153,7 +158,7 @@ QQuickAnimatorJob *QQuickBusyIndicatorAnimator::createJob() const return new QQuickBusyIndicatorAnimatorJob; } -QQuickBusyIndicatorAnimatorJob::QQuickBusyIndicatorAnimatorJob() +QQuickBusyIndicatorAnimatorJob::QQuickBusyIndicatorAnimatorJob() : m_node(Q_NULLPTR) { } @@ -161,13 +166,18 @@ QQuickBusyIndicatorAnimatorJob::~QQuickBusyIndicatorAnimatorJob() { } +void QQuickBusyIndicatorAnimatorJob::initialize(QQuickAnimatorController *controller) +{ + QQuickAnimatorJob::initialize(controller); + m_node = QQuickItemPrivate::get(m_target)->childContainerNode(); +} + void QQuickBusyIndicatorAnimatorJob::updateCurrentTime(int time) { - if (!m_target) + if (!m_node) return; - QSGNode *childContainerNode = QQuickItemPrivate::get(m_target)->childContainerNode(); - QSGSimpleRectNode *rootRectNode = static_cast(childContainerNode->firstChild()); + QSGSimpleRectNode *rootRectNode = static_cast(m_node->firstChild()); if (!rootRectNode) return; @@ -204,6 +214,12 @@ void QQuickBusyIndicatorAnimatorJob::writeBack() void QQuickBusyIndicatorAnimatorJob::nodeWasDestroyed() { + m_node = Q_NULLPTR; +} + +void QQuickBusyIndicatorAnimatorJob::afterNodeSync() +{ + m_node = QQuickItemPrivate::get(m_target)->childContainerNode(); } QT_END_NAMESPACE -- cgit v1.2.3