mirror of
https://github.com/jellyfin/jellyfin-desktop.git
synced 2026-10-27 00:56:07 +00:00
Three fixes for cross-distro compatibility: - Keep libvdpau.so in the bundle. It's a dispatcher library, not a GPU driver. The backend drivers in /usr/lib/vdpau/ are still excluded. Without the dispatcher, the AppImage fails to start on distros where libvdpau isn't installed by default (e.g. Ubuntu 24.04). - Replace the QtWebEngineProcess bash wrapper with a statically-linked C binary. The bash wrapper was crashing on Ubuntu because the host's /bin/bash was loaded by the host's dynamic linker, which then picked up the bundled Arch glibc via LD_LIBRARY_PATH — an ABI mismatch that segfaults. A static binary has no shared library dependencies, so LD_LIBRARY_PATH is irrelevant to it. - Improve APPDIR derivation in the wrapper. Instead of relying solely on the APPDIR environment variable (which may not be inherited by subprocesses), derive it from the binary's own path via /proc/self/exe.
69 lines
2.1 KiB
C
69 lines
2.1 KiB
C
/*
|
|
* Statically-linked wrapper for QtWebEngineProcess.
|
|
*
|
|
* Qt WebEngine launches this as a subprocess. Because the parent sets
|
|
* LD_LIBRARY_PATH to the AppImage's bundled libraries, a shell-script
|
|
* wrapper would crash: the host's /bin/bash gets loaded by the host's
|
|
* dynamic linker, which then pulls in the *bundled* glibc — an ABI
|
|
* mismatch that segfaults on distros whose glibc differs from the build
|
|
* host (e.g. Ubuntu vs Arch).
|
|
*
|
|
* A static binary sidesteps the problem entirely: it has no shared
|
|
* library dependencies, so LD_LIBRARY_PATH is irrelevant. It simply
|
|
* re-execs the real QtWebEngineProcess binary through the bundled
|
|
* ld-linux with an explicit --library-path.
|
|
*/
|
|
|
|
#include <limits.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <unistd.h>
|
|
|
|
int main(int argc, char *argv[])
|
|
{
|
|
char self[PATH_MAX];
|
|
ssize_t len = readlink("/proc/self/exe", self, sizeof(self) - 1);
|
|
if (len < 0)
|
|
_exit(127);
|
|
self[len] = '\0';
|
|
|
|
/* Derive APPDIR: this binary lives under $APPDIR/usr/lib/...,
|
|
so the first /usr/lib/ in the path marks the boundary. */
|
|
char *p = strstr(self, "/usr/lib/");
|
|
if (!p)
|
|
_exit(127);
|
|
|
|
int appdir_len = (int)(p - self);
|
|
|
|
char ldlinux[PATH_MAX];
|
|
snprintf(ldlinux, sizeof(ldlinux),
|
|
"%.*s/usr/lib/ld-linux-x86-64.so.2", appdir_len, self);
|
|
|
|
char real_bin[PATH_MAX + 8];
|
|
snprintf(real_bin, sizeof(real_bin), "%s.real", self);
|
|
|
|
char lib_path[PATH_MAX * 2];
|
|
snprintf(lib_path, sizeof(lib_path),
|
|
"%.*s/usr/lib"
|
|
":/usr/lib64:/usr/lib:/lib64:/lib"
|
|
":/usr/lib/x86_64-linux-gnu:/lib/x86_64-linux-gnu",
|
|
appdir_len, self);
|
|
|
|
/* argv: ld-linux --inhibit-cache --library-path <path> <real> [original args…] */
|
|
char **new_argv = calloc((size_t)(argc + 5), sizeof(char *));
|
|
if (!new_argv)
|
|
_exit(127);
|
|
|
|
new_argv[0] = ldlinux;
|
|
new_argv[1] = "--inhibit-cache";
|
|
new_argv[2] = "--library-path";
|
|
new_argv[3] = lib_path;
|
|
new_argv[4] = real_bin;
|
|
for (int i = 1; i < argc; i++)
|
|
new_argv[i + 4] = argv[i];
|
|
|
|
execv(ldlinux, new_argv);
|
|
_exit(127);
|
|
}
|