From a609554c031fd57d9a2a3905f5a02cc6b4aa19e9 Mon Sep 17 00:00:00 2001 From: Louis du Verdier Date: Mon, 2 Apr 2018 20:25:37 +0200 Subject: Fix crash when changing the source of AnimatedImage after a frame change QMovie emits the signals updated() and frameChanged(), and restarts right after its timer to prepare for the next frame. Since AnimatedImage destroys its underlying QMovie when its source changes, the lines after emit frameChanged() in QMovie will use free'd memory and will most of the time produce a crash. This fix delays the destruction of the underlying QMovie of AnimatedImage using deleteLater() to prevent this kind of behavior from happening without impact/behavior change in the code of QMovie. Unit tests added as well to cover this situation. This commit also fixes a similar crash when Component.onCompleted is called and when the source changes in the associated callback. Task-number: QTBUG-67427 Change-Id: Ic6568a1bc251e5fa2ee1cf8e5f50eaa56c3007db Reviewed-by: VaL Doroshchuk Reviewed-by: Shawn Rutledge Reviewed-by: Louis du Verdier --- src/quick/items/qquickanimatedimage.cpp | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) (limited to 'src/quick/items/qquickanimatedimage.cpp') diff --git a/src/quick/items/qquickanimatedimage.cpp b/src/quick/items/qquickanimatedimage.cpp index 26dfdb07a6..075c4a7d72 100644 --- a/src/quick/items/qquickanimatedimage.cpp +++ b/src/quick/items/qquickanimatedimage.cpp @@ -426,15 +426,18 @@ void QQuickAnimatedImage::movieRequestFinished() } bool pausedAtStart = d->paused; - if (d->playing) + if (d->movie && d->playing) d->movie->start(); - if (pausedAtStart) + if (d->movie && pausedAtStart) d->movie->setPaused(true); - if (d->paused || !d->playing) { + if (d->movie && (d->paused || !d->playing)) { d->movie->jumpToFrame(d->presetCurrentFrame); d->presetCurrentFrame = 0; } - d->setPixmap(*d->infoForCurrentFrame(qmlEngine(this))); + + QQuickPixmap *pixmap = d->infoForCurrentFrame(qmlEngine(this)); + if (pixmap) + d->setPixmap(*pixmap); if (isPlaying() != d->oldPlaying) emit playingChanged(); @@ -512,7 +515,10 @@ void QQuickAnimatedImagePrivate::setMovie(QMovie *m) Q_Q(QQuickAnimatedImage); const int oldFrameCount = q->frameCount(); - delete movie; + if (movie) { + movie->disconnect(); + movie->deleteLater(); + } movie = m; if (oldFrameCount != q->frameCount()) -- cgit v1.2.3