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 <sami.shalayel@qt.io>
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
This commit is contained in:
Ulf Hermann 2025-09-08 13:37:06 +02:00
parent a44dac1dc3
commit f94a727bd6
2 changed files with 26 additions and 3 deletions

View File

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

View File

@ -1,10 +1,12 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtQml/qqmlengine.h>
#include <QtTest/qtest.h>
#include <QtQml/private/qabstractanimationjob_p.h>
#include <QtQml/private/qanimationgroupjob_p.h>
#include <QTest>
#include <private/qabstractanimationjob_p.h>
#include <private/qanimationgroupjob_p.h>
#include <private/qcoreapplication_p.h>
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<QCoreApplicationPrivate *>(QObjectPrivate::get(QCoreApplication::instance()))
->cleanupThreadData();
}
}
QTEST_MAIN(tst_QAbstractAnimationJob)