From f94a727bd677e1869842a7edd0841aba9836a3c7 Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Mon, 8 Sep 2025 13:37:06 +0200 Subject: [PATCH] QtQml: Unregister QML animation timer on deletion The QUnifiedTimer generally outlives the QML animation timer and needs to be notified about that latter's deletion. Otherwise it will hold a dangling pointer. Pick-to: 6.10 6.9 6.8 Fixes: QTBUG-136629 Change-Id: I52b7f2f3ae716128e4acac628ea29477fc17b677 Reviewed-by: Sami Shalayel Reviewed-by: Fabian Kosmale --- src/qml/animations/qabstractanimationjob.cpp | 2 ++ .../tst_qabstractanimationjob.cpp | 27 ++++++++++++++++--- 2 files changed, 26 insertions(+), 3 deletions(-) diff --git a/src/qml/animations/qabstractanimationjob.cpp b/src/qml/animations/qabstractanimationjob.cpp index a50685ba50..82d807af7e 100644 --- a/src/qml/animations/qabstractanimationjob.cpp +++ b/src/qml/animations/qabstractanimationjob.cpp @@ -57,6 +57,8 @@ QQmlAnimationTimer::~QQmlAnimationTimer() unsetJobTimer(animation); for (const auto &animation : std::as_const(runningPauseAnimations)) unsetJobTimer(animation); + + QUnifiedTimer::stopAnimationTimer(this); } QQmlAnimationTimer *QQmlAnimationTimer::instance(bool create) diff --git a/tests/auto/qml/animation/qabstractanimationjob/tst_qabstractanimationjob.cpp b/tests/auto/qml/animation/qabstractanimationjob/tst_qabstractanimationjob.cpp index 471f3df39e..1fd5629f90 100644 --- a/tests/auto/qml/animation/qabstractanimationjob/tst_qabstractanimationjob.cpp +++ b/tests/auto/qml/animation/qabstractanimationjob/tst_qabstractanimationjob.cpp @@ -1,10 +1,12 @@ // Copyright (C) 2016 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only +#include +#include -#include -#include -#include +#include +#include +#include class tst_QAbstractAnimationJob : public QObject { @@ -23,6 +25,7 @@ private slots: void avoidJumpAtStart(); void avoidJumpAtStartWithStop(); void avoidJumpAtStartWithRunning(); + void deleteAnimationTimer(); }; class TestableQAbstractAnimation : public QAbstractAnimationJob @@ -184,6 +187,24 @@ void tst_QAbstractAnimationJob::avoidJumpAtStartWithRunning() QVERIFY(anim3.currentTime() < 50); } +void tst_QAbstractAnimationJob::deleteAnimationTimer() +{ + for (int i = 0; i < 10; ++i) { + { + TestableQAbstractAnimation mainAnimation; + mainAnimation.setDuration(100); + mainAnimation.start(); + QTRY_VERIFY(mainAnimation.isRunning()); + QTRY_VERIFY(mainAnimation.currentTime() > 50); + } + + // We can tear down the thread data that holds the animation timer. This does not cause + // the QUnifiedTimer to hold a dangling pointer next timer around. + static_cast(QObjectPrivate::get(QCoreApplication::instance())) + ->cleanupThreadData(); + } +} + QTEST_MAIN(tst_QAbstractAnimationJob)