1From 9bc14b7363f4da0ea1f71db3a952a998435a592b Mon Sep 17 00:00:00 2001 2From: Eskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@qt.io> 3Date: Thu, 22 Apr 2021 08:42:33 +0200 4Subject: [PATCH 02/17] client: Gracefully handle shutdown and window hiding 5 6When a window is hidden or destroyed, the render thread may already 7be rendering. We need to properly read-lock the surface pointer 8when it is in use and exit when it becomes null. 9 10Note that there is also a potential crash in the Mesa GL driver 11where it keeps a proxy to the wl_surface, so if we delete this 12while we are still rendering, it can crash inside the driver. 13This is not addressed by this patch, and has not been reproduced 14on any other drivers so far. 15 16[ChangeLog][Client] Fixed a crash that could happen when hiding 17or closing windows while Qt Quick was actively rendering on 18a different thread. 19 20Pick-to: 6.0 6.1 5.15 21Fixes: QTBUG-91264 22Fixes: QTBUG-90037 23Task-number: QTBUG-92249 24Change-Id: I029b123b83c58740321e8b90a463ced748d8bcf4 25Reviewed-by: Laszlo Agocs <laszlo.agocs@qt.io> 26Reviewed-by: David Edmundson <davidedmundson@kde.org> 27 28Conflicts: 29 src/client/qwaylandwindow.cpp 30 src/hardwareintegration/client/wayland-egl/qwaylandglcontext.cpp 31 32(cherry picked from commit b19b0fbaf775e8b8eda1e03c265a5393d618c6c0) 33Signed-off-by: Jeffy Chen <jeffy.chen@rock-chips.com> 34--- 35 src/client/qwaylandwindow.cpp | 15 +++++++++++++-- 36 src/client/qwaylandwindow_p.h | 2 +- 37 2 files changed, 14 insertions(+), 3 deletions(-) 38 39diff --git a/src/client/qwaylandwindow.cpp b/src/client/qwaylandwindow.cpp 40index ceaa4c7..6cbd315 100644 41--- a/src/client/qwaylandwindow.cpp 42+++ b/src/client/qwaylandwindow.cpp 43@@ -414,6 +414,7 @@ void QWaylandWindow::closePopups(QWaylandWindow *parent) 44 45 QPlatformScreen *QWaylandWindow::calculateScreenFromSurfaceEvents() const 46 { 47+ QReadLocker lock(&mSurfaceLock); 48 if (mSurface) { 49 if (auto *screen = mSurface->oldestEnteredScreen()) 50 return screen; 51@@ -552,6 +553,10 @@ void QWaylandWindow::sendRecursiveExposeEvent() 52 53 void QWaylandWindow::attach(QWaylandBuffer *buffer, int x, int y) 54 { 55+ QReadLocker locker(&mSurfaceLock); 56+ if (mSurface == nullptr) 57+ return; 58+ 59 if (buffer) { 60 Q_ASSERT(!buffer->committed()); 61 handleUpdate(); 62@@ -605,6 +610,8 @@ void QWaylandWindow::commit(QWaylandBuffer *buffer, const QRegion &damage) 63 qCDebug(lcWaylandBackingstore) << "Buffer already committed, ignoring."; 64 return; 65 } 66+ 67+ QReadLocker locker(&mSurfaceLock); 68 if (!mSurface) 69 return; 70 71@@ -624,7 +631,9 @@ void QWaylandWindow::commit(QWaylandBuffer *buffer, const QRegion &damage) 72 73 void QWaylandWindow::commit() 74 { 75- mSurface->commit(); 76+ QReadLocker locker(&mSurfaceLock); 77+ if (mSurface != nullptr) 78+ mSurface->commit(); 79 } 80 81 const wl_callback_listener QWaylandWindow::callbackListener = { 82@@ -723,6 +732,7 @@ QPointF QWaylandWindow::mapFromWlSurface(const QPointF &surfacePosition) const 83 84 wl_surface *QWaylandWindow::wlSurface() 85 { 86+ QReadLocker locker(&mSurfaceLock); 87 return mSurface ? mSurface->object() : nullptr; 88 } 89 90@@ -747,7 +757,8 @@ QWaylandScreen *QWaylandWindow::waylandScreen() const 91 92 void QWaylandWindow::handleContentOrientationChange(Qt::ScreenOrientation orientation) 93 { 94- if (mDisplay->compositorVersion() < 2) 95+ QReadLocker locker(&mSurfaceLock); 96+ if (mSurface == nullptr || mDisplay->compositorVersion() < 2) 97 return; 98 99 wl_output_transform transform; 100diff --git a/src/client/qwaylandwindow_p.h b/src/client/qwaylandwindow_p.h 101index cb9135f..c0a7634 100644 102--- a/src/client/qwaylandwindow_p.h 103+++ b/src/client/qwaylandwindow_p.h 104@@ -288,7 +288,7 @@ private: 105 106 static QWaylandWindow *mMouseGrab; 107 108- QReadWriteLock mSurfaceLock; 109+ mutable QReadWriteLock mSurfaceLock; 110 111 friend class QWaylandSubSurface; 112 }; 113-- 1142.20.1 115 116