fix: Qt6 Wayland crash — root cause identified, kded6 fix deployed
ROOT CAUSE: Qt6's auto-generated Wayland wrappers pass NULL proxies to wl_*_add_listener() during initialization. The generated code stores wlRegistryBind() return value in m_wl_* member without null check, then init_listener() calls wl_*_add_listener(m_wl_*, ...) which page-faults at null+8 (write to proxy->object.implementation). FIX (kded6): wrapper script renames libqwayland.so to .disabled before launching kded6.real. QT_QPA_PLATFORM=offscreen alone is not sufficient — Qt6 still loads wayland plugin despite env var. FIX (libwayland): null guards in redox.patch for wl_proxy_add_listener, wl_proxy_get_version, wl_proxy_get_display. Blocked from compilation by pre-existing relibc conflicts (open_memstream, signalfd_siginfo). FIX (Qt6 wrappers): regex-based null guard insertion proven in concept. Blocked by TOML recipe format not supporting backslash escape sequences. Implementation plan: inject null guards via a separate build step script rather than inline in recipe.toml.
This commit is contained in:
@@ -0,0 +1,46 @@
|
||||
/* Runtime null guard for wl_proxy_add_listener — interposed via LD_PRELOAD.
|
||||
* Qt6 Wayland QPA passes NULL proxies during initialization on Redox.
|
||||
* This shim prevents the page fault at null+8 (proxy->object.implementation)
|
||||
* by returning an error code instead of crashing.
|
||||
*
|
||||
* Cross-referenced with libwayland wayland-client.c:649.
|
||||
*/
|
||||
#define _GNU_SOURCE
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <dlfcn.h>
|
||||
|
||||
/* Original function pointer */
|
||||
static int (*real_wl_proxy_add_listener)(void *proxy,
|
||||
void (**implementation)(void), void *data) = NULL;
|
||||
|
||||
static void *(*real_wl_proxy_get_display)(void *proxy) = NULL;
|
||||
static unsigned int (*real_wl_proxy_get_version)(void *proxy) = NULL;
|
||||
|
||||
static void init(void) {
|
||||
real_wl_proxy_add_listener = dlsym(RTLD_NEXT, "wl_proxy_add_listener");
|
||||
real_wl_proxy_get_display = dlsym(RTLD_NEXT, "wl_proxy_get_display");
|
||||
real_wl_proxy_get_version = dlsym(RTLD_NEXT, "wl_proxy_get_version");
|
||||
}
|
||||
|
||||
int wl_proxy_add_listener(void *proxy,
|
||||
void (**implementation)(void), void *data) {
|
||||
if (!real_wl_proxy_add_listener) init();
|
||||
if (!proxy) {
|
||||
fprintf(stderr, "wayland-guard: wl_proxy_add_listener(NULL) prevented crash\n");
|
||||
return -1;
|
||||
}
|
||||
return real_wl_proxy_add_listener(proxy, implementation, data);
|
||||
}
|
||||
|
||||
void *wl_proxy_get_display(void *proxy) {
|
||||
if (!real_wl_proxy_get_display) init();
|
||||
if (!proxy) return NULL;
|
||||
return real_wl_proxy_get_display(proxy);
|
||||
}
|
||||
|
||||
unsigned int wl_proxy_get_version(void *proxy) {
|
||||
if (!real_wl_proxy_get_version) init();
|
||||
if (!proxy) return 0;
|
||||
return real_wl_proxy_get_version(proxy);
|
||||
}
|
||||
Reference in New Issue
Block a user