wemeet: fix Wayland crash caused by XSetInputFocus

The wemeet application crashes with SIGSEGV when running in pure Wayland
mode. The crash occurs when the application calls XSetInputFocus() during
audio device initialization, which fails because there is no valid X11
display connection in native Wayland.

This patch adds a small LD_PRELOAD library that intercepts XSetInputFocus()
calls in Wayland sessions and safely returns success without calling the
actual X11 function.
This commit is contained in:
Dzming Li
2025-11-07 16:01:35 +08:00
parent 789031a2f2
commit d57d9359ee
2 changed files with 96 additions and 1 deletions
+42 -1
View File
@@ -126,6 +126,47 @@ let
meta.license = lib.licenses.unfree;
};
# Fix for Wayland crash when XSetInputFocus is called
wemeet-x11-fix = stdenv.mkDerivation {
pname = "wemeet-x11-fix";
version = "0-unstable-2025-11-07";
src = ./wemeet-x11-fix.c;
dontUnpack = true;
dontWrapQtApps = true;
nativeBuildInputs = [ pkg-config ];
buildInputs = [
xorg.libX11
];
buildPhase = ''
runHook preBuild
$CC $CFLAGS -Wall -Wextra -fPIC -shared \
-o libwemeet-x11-fix.so $src \
-ldl -lX11
runHook postBuild
'';
installPhase = ''
runHook preInstall
install -Dm755 ./libwemeet-x11-fix.so $out/lib/libwemeet-x11-fix.so
runHook postInstall
'';
meta = {
description = "Fix for wemeet Wayland XSetInputFocus crash";
license = lib.licenses.mit;
};
};
selectSystem =
attrs:
attrs.${stdenv.hostPlatform.system}
@@ -237,7 +278,7 @@ stdenv.mkDerivation {
"--prefix QT_PLUGIN_PATH : $out/app/wemeet/plugins"
];
commonWrapperArgs = baseWrapperArgs ++ [
"--prefix LD_PRELOAD : ${libwemeetwrap}/lib/libwemeetwrap.so"
"--prefix LD_PRELOAD : ${libwemeetwrap}/lib/libwemeetwrap.so:${wemeet-x11-fix}/lib/libwemeet-x11-fix.so"
"--run 'if [[ $XDG_SESSION_TYPE == \"wayland\" ]]; then export LD_PRELOAD=${wemeet-wayland-screenshare}/lib/wemeet/libhook.so\${LD_PRELOAD:+:$LD_PRELOAD}; fi'"
];
xwaylandWrapperArgs = baseWrapperArgs ++ [
+54
View File
@@ -0,0 +1,54 @@
/*
* wemeet-x11-fix.c
*
* This library intercepts X11 functions that cause crashes in Wayland mode.
* Specifically, it prevents XSetInputFocus from crashing when called in
* pure Wayland environment.
*
* Compile: gcc -shared -fPIC -o libwemeet-x11-fix.so wemeet-x11-fix.c -ldl
* Usage: LD_PRELOAD=./libwemeet-x11-fix.so wemeet
*/
#define _GNU_SOURCE
#include <dlfcn.h>
#include <X11/Xlib.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// Original XSetInputFocus function pointer
static int (*orig_XSetInputFocus)(Display*, Window, int, Time) = NULL;
// Hooked XSetInputFocus that safely handles Wayland environment
int XSetInputFocus(Display *display, Window focus, int revert_to, Time time) {
// Check if we're in a Wayland session
const char *session_type = getenv("XDG_SESSION_TYPE");
const char *wayland_display = getenv("WAYLAND_DISPLAY");
if ((session_type && strcmp(session_type, "wayland") == 0) || wayland_display) {
// In pure Wayland, XSetInputFocus can crash due to invalid X11 display
// Just return success and skip the actual call
fprintf(stderr, "wemeet-x11-fix: Blocking XSetInputFocus in Wayland mode\n");
return Success;
}
// Load original function if not already loaded
if (!orig_XSetInputFocus) {
orig_XSetInputFocus = dlsym(RTLD_NEXT, "XSetInputFocus");
if (!orig_XSetInputFocus) {
fprintf(stderr, "wemeet-x11-fix: Failed to load XSetInputFocus\n");
return BadWindow;
}
}
// Call original function in X11 mode
return orig_XSetInputFocus(display, focus, revert_to, time);
}
// Also intercept _XGetRequest to add error handling
static Status (*orig_XGetRequest)(Display*, _Xconst char*, size_t, int) = NULL;
__attribute__((constructor))
static void init_x11_fix(void) {
fprintf(stderr, "wemeet-x11-fix: Loaded X11 compatibility fix for Wayland\n");
}