Skip to content

Commit 365bf16

Browse files
outfoxxedItsLemmy
andcommitted
wayland: hook wl_proxy_get_listener avoiding QTBUG-145022 crash
Co-authored-by: Lemmy <studio@quadbyte.net>
1 parent 6705e2d commit 365bf16

5 files changed

Lines changed: 54 additions & 1 deletion

File tree

changelog/next.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ set shell id.
5858
- Fixed ToplevelManager not clearing activeToplevel on deactivation.
5959
- Desktop action order is now preserved.
6060
- Fixed partial socket reads in greetd and hyprland on slow machines.
61+
- Worked around Qt bug causing crashes when plugging and unplugging monitors.
6162

6263
## Packaging Changes
6364

src/wayland/CMakeLists.txt

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,13 +73,21 @@ endfunction()
7373
# -----
7474

7575
qt_add_library(quickshell-wayland STATIC
76+
wl_proxy_safe_deref.cpp
7677
platformmenu.cpp
7778
popupanchor.cpp
7879
xdgshell.cpp
7980
util.cpp
8081
output_tracking.cpp
8182
)
8283

84+
# required for wl_proxy_safe_deref
85+
target_link_libraries(quickshell-wayland PRIVATE ${CMAKE_DL_LIBS})
86+
target_link_options(quickshell PRIVATE
87+
"LINKER:--export-dynamic-symbol=wl_proxy_get_listener"
88+
"LINKER:--require-defined=wl_proxy_get_listener"
89+
)
90+
8391
# required to make sure the constructor is linked
8492
add_library(quickshell-wayland-init OBJECT init.cpp)
8593

src/wayland/init.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#include "wlr_layershell/wlr_layershell.hpp"
1111
#endif
1212

13+
void installWlProxySafeDeref(); // NOLINT(misc-use-internal-linkage)
1314
void installPlatformMenuHook(); // NOLINT(misc-use-internal-linkage)
1415
void installPopupPositioner(); // NOLINT(misc-use-internal-linkage)
1516

@@ -33,6 +34,7 @@ class WaylandPlugin: public QsEnginePlugin {
3334
}
3435

3536
void init() override {
37+
installWlProxySafeDeref();
3638
installPlatformMenuHook();
3739
installPopupPositioner();
3840
}

src/wayland/windowmanager/windowset.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,9 @@
88
#include <qobjectdefs.h>
99
#include <qproperty.h>
1010

11+
#include "../../windowmanager/screenprojection.hpp"
1112
#include "../../windowmanager/windowmanager.hpp"
1213
#include "../../windowmanager/windowset.hpp"
13-
#include "../../windowmanager/screenprojection.hpp"
1414
#include "ext_workspace.hpp"
1515

1616
namespace qs::wm::wayland {
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
2+
#include <dlfcn.h>
3+
#include <qlogging.h>
4+
#include <qloggingcategory.h>
5+
#include <wayland-client-core.h>
6+
#include <wayland-util.h>
7+
8+
#include "../core/logcat.hpp"
9+
10+
namespace {
11+
QS_LOGGING_CATEGORY(logDeref, "quickshell.wayland.safederef", QtWarningMsg);
12+
using wl_proxy_get_listener_t = const void* (*) (wl_proxy*);
13+
wl_proxy_get_listener_t original_wl_proxy_get_listener = nullptr; // NOLINT
14+
} // namespace
15+
16+
extern "C" {
17+
WL_EXPORT const void* wl_proxy_get_listener(struct wl_proxy* proxy) {
18+
// Avoid null derefs of protocol objects in qtbase.
19+
// https://qt-project.atlassian.net/browse/QTBUG-145022
20+
if (!proxy) [[unlikely]] {
21+
qCCritical(logDeref) << "wl_proxy_get_listener called with a null proxy!";
22+
return nullptr;
23+
}
24+
25+
return original_wl_proxy_get_listener(proxy);
26+
}
27+
}
28+
29+
// NOLINTBEGIN (concurrency-mt-unsafe)
30+
void installWlProxySafeDeref() {
31+
dlerror(); // clear old errors
32+
33+
original_wl_proxy_get_listener =
34+
reinterpret_cast<wl_proxy_get_listener_t>(dlsym(RTLD_NEXT, "wl_proxy_get_listener"));
35+
36+
if (auto* error = dlerror()) {
37+
qCCritical(logDeref) << "Failed to find wl_proxy_get_listener for hooking:" << error;
38+
} else {
39+
qCInfo(logDeref) << "Installed wl_proxy_get_listener hook.";
40+
}
41+
}
42+
// NOLINTEND

0 commit comments

Comments
 (0)