Skip to content

Commit 271d469

Browse files
committed
wayland: resolve session lock crashes on unlock, sleep, and output changes
- Destroys Wayland lock surface roles synchronously prior to sending unlock_and_destroy. - Avoids creating lock surfaces on invalid/placeholder/removed outputs to prevent early initialization failures. - Fixes Qt 6.6.3 compilation compatibility when QPointer uses incomplete forward-declared types. - Reverts memory cleanup to asynchronous deleteLater() for QML safety.
1 parent b66495f commit 271d469

6 files changed

Lines changed: 25 additions & 7 deletions

File tree

changelog/next.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,4 @@
44
- Fixed WlSessionLockSurface.visible crashing if accessed before backing surface creation.
55
- Fixed mpris players returning `rate` for `minRate` and `maxRate`.
66
- Fixed missing/wrong change signals on various properties.
7+
- Fixed multiple session lock client crashes on sleep, wake, DPMS, and unlocking.

src/wayland/session_lock.cpp

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -56,9 +56,12 @@ void WlSessionLock::updateSurfaces(bool show, WlSessionLock* old) {
5656
auto screens = QGuiApplication::screens();
5757

5858
screens.removeIf([](QScreen* screen) {
59-
if (dynamic_cast<QtWaylandClient::QWaylandScreen*>(screen->handle()) == nullptr) {
59+
auto* waylandScreen = dynamic_cast<QtWaylandClient::QWaylandScreen*>(screen->handle());
60+
if (waylandScreen == nullptr || waylandScreen->isPlaceholder()
61+
|| waylandScreen->output() == nullptr)
62+
{
6063
qDebug() << "Not creating lock surface for screen" << screen
61-
<< "as it is not backed by a wayland screen.";
64+
<< "as it is not backed by a valid wayland output.";
6265

6366
return true;
6467
}
@@ -144,7 +147,6 @@ void WlSessionLock::unlock() {
144147
for (auto* surface: this->surfaces) {
145148
surface->deleteLater();
146149
}
147-
148150
this->surfaces.clear();
149151

150152
emit this->lockStateChanged();
@@ -207,6 +209,7 @@ WlSessionLockSurface::WlSessionLockSurface(QObject* parent)
207209

208210
WlSessionLockSurface::~WlSessionLockSurface() {
209211
if (this->window != nullptr) {
212+
this->window->destroy();
210213
this->window->deleteLater();
211214
}
212215
}

src/wayland/session_lock.hpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -185,4 +185,6 @@ private slots:
185185
QScreen* mScreen = nullptr;
186186
QColor mColor = Qt::white;
187187
LockWindowExtension* ext;
188+
189+
friend class WlSessionLock;
188190
};

src/wayland/session_lock/session_lock.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
#include <qlogging.h>
55
#include <qobject.h>
66
#include <qwindow.h>
7+
#include <wayland-client.h> // NOLINT(misc-include-cleaner)
78

89
#include "lock.hpp"
910
#include "manager.hpp"
@@ -49,6 +50,8 @@ bool SessionLockManager::isLocked() const { return this->mLock != nullptr; }
4950
bool SessionLockManager::sessionLocked() { return manager()->isLocked(); }
5051
bool SessionLockManager::isSecure() { return manager()->isSecure(); }
5152

53+
LockWindowExtension::LockWindowExtension(QObject* parent): QObject(parent) {}
54+
5255
LockWindowExtension::~LockWindowExtension() {
5356
if (this->surface != nullptr) {
5457
this->surface->setExtension(nullptr);

src/wayland/session_lock/session_lock.hpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#pragma once
22

33
#include <qobject.h>
4+
#include <qpointer.h>
45
#include <qtclasshelpermacros.h>
56
#include <qtmetamacros.h>
67
#include <qwindow.h>
@@ -59,7 +60,7 @@ class LockWindowExtension: public QObject {
5960
Q_OBJECT;
6061

6162
public:
62-
explicit LockWindowExtension(QObject* parent = nullptr): QObject(parent) {}
63+
explicit LockWindowExtension(QObject* parent = nullptr);
6364
~LockWindowExtension() override;
6465
Q_DISABLE_COPY_MOVE(LockWindowExtension);
6566

src/wayland/session_lock/surface.cpp

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,8 @@ QSWaylandSessionLockSurface::QSWaylandSessionLockSurface(QtWaylandClient::QWayla
2121
qFatal() << "QSWaylandSessionLockSurface created with null LockWindowExtension";
2222
}
2323

24-
if (this->ext->lock == nullptr) {
24+
auto* lock = this->ext->lock;
25+
if (lock == nullptr) {
2526
qFatal() << "QSWaylandSessionLock for QSWaylandSessionLockSurface died";
2627
}
2728

@@ -34,11 +35,18 @@ QSWaylandSessionLockSurface::QSWaylandSessionLockSurface(QtWaylandClient::QWayla
3435
qFatal() << "Session lock screen does not correspond to a real screen. Force closing window";
3536
}
3637

37-
this->init(this->ext->lock->get_lock_surface(window->waylandSurface()->object(), output));
38+
this->init(lock->get_lock_surface(window->waylandSurface()->object(), output));
3839
}
3940

4041
QSWaylandSessionLockSurface::~QSWaylandSessionLockSurface() {
41-
if (this->ext != nullptr) this->ext->surface = nullptr;
42+
if (this->object() == nullptr) {
43+
return;
44+
}
45+
46+
if (this->ext != nullptr) {
47+
this->ext->surface = nullptr;
48+
}
49+
4250
this->destroy();
4351
}
4452

0 commit comments

Comments
 (0)