mirror of
https://github.com/quickshell-mirror/quickshell.git
synced 2026-10-27 02:54:36 +00:00
wayland: hook wl_proxy_get_listener avoiding QTBUG-145022 crash
Co-authored-by: Lemmy <[email protected]>
This commit is contained in:
5 files changed
+54
-1
No files matched your search
@@ -58,6 +58,7 @@ set shell id.
|
||||
- Fixed ToplevelManager not clearing activeToplevel on deactivation.
|
||||
- Desktop action order is now preserved.
|
||||
- Fixed partial socket reads in greetd and hyprland on slow machines.
|
||||
- Worked around Qt bug causing crashes when plugging and unplugging monitors.
|
||||
|
||||
## Packaging Changes
|
||||
|
||||
|
||||
@@ -73,6 +73,7 @@ endfunction()
|
||||
# -----
|
||||
|
||||
qt_add_library(quickshell-wayland STATIC
|
||||
wl_proxy_safe_deref.cpp
|
||||
platformmenu.cpp
|
||||
popupanchor.cpp
|
||||
xdgshell.cpp
|
||||
@@ -80,6 +81,13 @@ qt_add_library(quickshell-wayland STATIC
|
||||
output_tracking.cpp
|
||||
)
|
||||
|
||||
# required for wl_proxy_safe_deref
|
||||
target_link_libraries(quickshell-wayland PRIVATE ${CMAKE_DL_LIBS})
|
||||
target_link_options(quickshell PRIVATE
|
||||
"LINKER:--export-dynamic-symbol=wl_proxy_get_listener"
|
||||
"LINKER:--require-defined=wl_proxy_get_listener"
|
||||
)
|
||||
|
||||
# required to make sure the constructor is linked
|
||||
add_library(quickshell-wayland-init OBJECT init.cpp)
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#include "wlr_layershell/wlr_layershell.hpp"
|
||||
#endif
|
||||
|
||||
void installWlProxySafeDeref(); // NOLINT(misc-use-internal-linkage)
|
||||
void installPlatformMenuHook(); // NOLINT(misc-use-internal-linkage)
|
||||
void installPopupPositioner(); // NOLINT(misc-use-internal-linkage)
|
||||
|
||||
@@ -33,6 +34,7 @@ class WaylandPlugin: public QsEnginePlugin {
|
||||
}
|
||||
|
||||
void init() override {
|
||||
installWlProxySafeDeref();
|
||||
installPlatformMenuHook();
|
||||
installPopupPositioner();
|
||||
}
|
||||
|
||||
@@ -8,9 +8,9 @@
|
||||
#include <qobjectdefs.h>
|
||||
#include <qproperty.h>
|
||||
|
||||
#include "../../windowmanager/screenprojection.hpp"
|
||||
#include "../../windowmanager/windowmanager.hpp"
|
||||
#include "../../windowmanager/windowset.hpp"
|
||||
#include "../../windowmanager/screenprojection.hpp"
|
||||
#include "ext_workspace.hpp"
|
||||
|
||||
namespace qs::wm::wayland {
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
|
||||
#include <dlfcn.h>
|
||||
#include <qlogging.h>
|
||||
#include <qloggingcategory.h>
|
||||
#include <wayland-client-core.h>
|
||||
#include <wayland-util.h>
|
||||
|
||||
#include "../core/logcat.hpp"
|
||||
|
||||
namespace {
|
||||
QS_LOGGING_CATEGORY(logDeref, "quickshell.wayland.safederef", QtWarningMsg);
|
||||
using wl_proxy_get_listener_t = const void* (*) (wl_proxy*);
|
||||
wl_proxy_get_listener_t original_wl_proxy_get_listener = nullptr; // NOLINT
|
||||
} // namespace
|
||||
|
||||
extern "C" {
|
||||
WL_EXPORT const void* wl_proxy_get_listener(struct wl_proxy* proxy) {
|
||||
// Avoid null derefs of protocol objects in qtbase.
|
||||
// https://qt-project.atlassian.net/browse/QTBUG-145022
|
||||
if (!proxy) [[unlikely]] {
|
||||
qCCritical(logDeref) << "wl_proxy_get_listener called with a null proxy!";
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return original_wl_proxy_get_listener(proxy);
|
||||
}
|
||||
}
|
||||
|
||||
// NOLINTBEGIN (concurrency-mt-unsafe)
|
||||
void installWlProxySafeDeref() {
|
||||
dlerror(); // clear old errors
|
||||
|
||||
original_wl_proxy_get_listener =
|
||||
reinterpret_cast<wl_proxy_get_listener_t>(dlsym(RTLD_NEXT, "wl_proxy_get_listener"));
|
||||
|
||||
if (auto* error = dlerror()) {
|
||||
qCCritical(logDeref) << "Failed to find wl_proxy_get_listener for hooking:" << error;
|
||||
} else {
|
||||
qCInfo(logDeref) << "Installed wl_proxy_get_listener hook.";
|
||||
}
|
||||
}
|
||||
// NOLINTEND
|
||||
Reference in new issue
Block a user