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