fix(gui): strip host LD_LIBRARY_PATH from packaging + defensive GPU/icon fixes

Root cause of the packaged GUI crashing with SIGSEGV inside ld.so on user
machines (segfault at fixed +0x1ff36, undefined symbols nspr_use_zone_allocator
/ localtime64): the build host had LD_LIBRARY_PATH polluted by a third-party
runtime (/opt/cangjie), which electron-builder baked into the produced binary's
dependency resolution. Clean machines without that library then fail in the
dynamic loader before any app code runs.

- Makefile: every gui-* pack target now runs under `env -u LD_LIBRARY_PATH`
- main.js: app.disableHardwareAcceleration() before ready (avoids the common
  Chromium GPU-process SIGSEGV on hybrid-GPU/Wayland Linux hosts)
- main.js: window icon reads from process.resourcesPath (real file, not asar)
  — asar-path icons are a known GTK segfault source on Linux
This commit is contained in:
JianFeeeee
2026-08-17 19:50:34 +08:00
parent 8c5279b416
commit b9f2486037
2 changed files with 31 additions and 7 deletions

View File

@ -47,6 +47,15 @@ const CORE_EXE = path.join(
"bin",
process.platform === "win32" ? "llmsproxy.exe" : "llmsproxy",
);
// Packaged window icon: must be a REAL file on disk (extraResource), not an
// asar path — Electron/GTK pulls BrowserWindow icons from the filesystem and
// crashes (SIGSEGV) when given an asar virtual path on Linux.
// Dev: cmd/gui/build/icon.png.
const WINDOW_ICON = path.join(
app.isPackaged ? process.resourcesPath : __dirname,
"build",
"icon.png",
);
// default port for the embedded core (configurable via settings)
const DEFAULT_PORT = 8787;
@ -508,8 +517,9 @@ function createWindow() {
const menu = Menu.buildFromTemplate([]);
Menu.setApplicationMenu(menu);
mainWindow = new BrowserWindow({
// Window icon (taskbar/dock): same asset as the tray and package.
icon: path.join(__dirname, "build", "icon.png"),
// Window icon (taskbar/dock). Packaged: real file under resourcesPath (see
// WINDOW_ICON) — an asar path here makes GTK segfault on Linux.
icon: WINDOW_ICON,
// GNOME taskbar icons match the window's WM_CLASS (lowercase
// "modelrouter-gui") against StartupWMClass in the .desktop file.
backgroundColor: "#1f2937",
@ -639,6 +649,12 @@ ipcMain.handle("shell:openPath", (_, p) => {
// window control from renderer uses preload -> ipcMain above
// ---------- bootstrap ----------
// Defensive GPU handling: Electron's Chromium GPU process is a frequent
// source of hard crashes (SIGSEGV) on Linux, especially on hybrid-GPU and
// Wayland setups. The GUI host is an LLM management shell — a software
// renderer is perfectly fine. Must run before app.whenReady.
app.disableHardwareAcceleration();
const gotLock = app.requestSingleInstanceLock();
if (gotLock) {
app.on("second-instance", () => {