diff --git a/desktop/scripts/fix-appimage.sh b/desktop/scripts/fix-appimage.sh index 3cd6411996b..424d4bcd85c 100755 --- a/desktop/scripts/fix-appimage.sh +++ b/desktop/scripts/fix-appimage.sh @@ -25,13 +25,14 @@ # bundled libgst* core below to use the host's). Crucially, once that variable # is set it *replaces* GStreamer's compiled-in default search path rather than # adding to it, so the app finds ZERO plugins on every distro: -# "GStreamer element appsink not found" kills the WebKitWebProcess and the -# window never paints. An earlier revision of this script hid the failure on +# "GStreamer element autoaudiosink not found" then WebKitWebProcess SIGABRT +# (blank window). An earlier revision of this script hid the failure on # Debian only by symlinking usr/lib/gstreamer-1.0 to the Debian multiarch dir # (/usr/lib/x86_64-linux-gnu/gstreamer-1.0); that symlink dangles on Arch and -# Fedora, and the "safe fallback to default discovery" it assumed does not -# exist -- a set GST_PLUGIN_SYSTEM_PATH_1_0 disables the default. A broken run -# also poisons ~/.cache/gstreamer-1.0/registry.x86_64.bin. +# Fedora. Unsetting the override is necessary but not sufficient: GStreamer's +# compiled-in default can miss host plugin dirs (Arch/Fedora live at +# /usr/lib/gstreamer-1.0, Debian at the multiarch path), and a failed scan +# poisons ~/.cache/gstreamer-1.0/registry.x86_64.bin. # # 3. WebKit helper mismatch (latent): the bundled WebKit helpers # (WebKitNetworkProcess/WebKitWebProcess) have RUNPATH=$ORIGIN only, and @@ -45,9 +46,11 @@ # Fix: (a) remove the offending libs so the app uses the system copies (newer and # ABI-compatible on any distro shipping glib >= 2.72 / Ubuntu 22.04+), and # (b) install a launcher shim in front of the app binary that strips the -# bundle-pointing GST_PLUGIN_* overrides AppRun.wrapped injects, letting the host -# GStreamer resolve plugins via its own default path (correct on Debian, Arch, and -# Fedora alike). The shim has to run *after* AppRun.wrapped: the wrapper rewrites +# bundle-pointing GST_PLUGIN_* overrides AppRun.wrapped injects and, if the +# user has not already set a host path, points GST_PLUGIN_SYSTEM_PATH_1_0 at +# existing host plugin dirs. The shim also isolates GST_REGISTRY under the app +# cache so a failed scan cannot poison the user-wide GStreamer registry. The +# shim has to run *after* AppRun.wrapped: the wrapper rewrites # the variable last -- after every apprun-hook -- so any value set before it is # discarded (verified empirically; a runtime GST_PLUGIN_SYSTEM_PATH_1_0 passed # into the AppImage does not survive). No tauri.conf.json knob can do this -- @@ -117,7 +120,10 @@ echo "==> Installing GStreamer launcher shim on the app binary" # plugins into. Because a set path *replaces* GStreamer's default instead of # extending it, the app finds zero plugins on any distro and WebKit aborts. The # wrapper rewrites the variable after every apprun-hook, so the only place to undo -# it is a shim between AppRun.wrapped and the real binary. First confirm the +# it is a shim between AppRun.wrapped and the real binary. The shim unsets +# bundle-pointing GST_PLUGIN_* values, then sets GST_PLUGIN_SYSTEM_PATH_1_0 to +# existing host plugin dirs (unsetting alone is not enough on Arch/Fedora) and +# isolates GST_REGISTRY under the app cache. First confirm the # wrapper still injects the override; if a tauri/linuxdeploy bump drops it, the # shim becomes a harmless no-op, but we want a human to re-verify rather than # silently ship — so fail loudly (mirrors the libwayland guard above). @@ -146,10 +152,12 @@ cat > "$APP_BIN" <<'SHIM' # linuxdeploy's AppRun.wrapped force-sets GST_PLUGIN_SYSTEM_PATH_1_0 to an empty # in-bundle dir ($APPDIR/usr/lib/gstreamer-1.0). A set path *replaces* the host's # default GStreamer search path, so the app finds zero plugins and WebKit aborts -# (blank window). Drop the bundle-pointing GST_PLUGIN_* overrides so the system -# GStreamer — which we use, having removed the bundled core libs — resolves -# plugins via its own default path on any distro. Values that don't point into -# this AppImage are the user's own and are preserved. +# (blank window). Drop bundle-pointing GST_PLUGIN_* overrides (user-set values +# that do not point into this AppImage are preserved), then if no host +# GST_PLUGIN_SYSTEM_PATH_1_0 remains, point it at existing host plugin dirs. +# Unsetting alone is not enough: compiled-in defaults miss Arch/Fedora paths. +# Isolate GST_REGISTRY under the app cache so a failed scan cannot poison +# ~/.cache/gstreamer-1.0/registry.x86_64.bin. here="$(dirname "$(readlink -f "$0")")" appdir="$(readlink -f "$here/../..")" for var in GST_PLUGIN_SYSTEM_PATH_1_0 GST_PLUGIN_SYSTEM_PATH \ @@ -160,6 +168,19 @@ for var in GST_PLUGIN_SYSTEM_PATH_1_0 GST_PLUGIN_SYSTEM_PATH \ unset "$var" fi done +if [[ -z "${GST_PLUGIN_SYSTEM_PATH_1_0:-}" ]]; then + host_gst_path= + for dir in /usr/lib/gstreamer-1.0 /usr/lib64/gstreamer-1.0 \ + /usr/lib/x86_64-linux-gnu/gstreamer-1.0; do + [[ -d "$dir" ]] || continue + host_gst_path="${host_gst_path:+$host_gst_path:}$dir" + done + if [[ -n "$host_gst_path" ]]; then + export GST_PLUGIN_SYSTEM_PATH_1_0="$host_gst_path" + fi +fi +export GST_REGISTRY="${XDG_CACHE_HOME:-$HOME/.cache}/xyz.block.buzz.app/gstreamer-1.0/registry.bin" +mkdir -p "$(dirname "$GST_REGISTRY")" exec -a "buzz-desktop" "$here/buzz-desktop.bin" "$@" SHIM chmod +x "$APP_BIN" diff --git a/docs/linux-rendering-troubleshooting.md b/docs/linux-rendering-troubleshooting.md index 4bc8e80eb83..11c246e30cd 100644 --- a/docs/linux-rendering-troubleshooting.md +++ b/docs/linux-rendering-troubleshooting.md @@ -7,6 +7,7 @@ This guide covers the most common rendering failures on Linux and how to resolve | Symptom | Likely cause | Fix | |---------|-------------|-----| | Blank or transparent window, then `SIGABRT` with `colrv1_configure_skpaint` in the output | COLRv1 color emoji font (AppImage only) | Upgrade to the latest AppImage (v0.5.2+) | +| Blank window, then `GStreamer element autoaudiosink not found` and WebKitWebProcess `SIGABRT` | AppImage uses host GStreamer; WebKit RELEASE_ASSERTs on a missing audio sink (`autoaudiosink` lives in gst-plugins-good) | Install `gst-plugins-good` (Arch) / `gstreamer1.0-plugins-good` (Debian). AppImage shim should set host plugin dirs. | | Blank window on startup / SIGSEGV when switching workspaces | dmabuf renderer incompatibility (NVIDIA or AppImage) | Prefer `WEBKIT_DMABUF_RENDERER_FORCE_SHM=1` (shipped automatically) or `--safe-rendering`. Do **not** set `WEBKIT_DISABLE_DMABUF_RENDERER=1` on current WebKitGTK — see [#3654](https://github.com/block/buzz/issues/3654). On Debian/Ubuntu with the proprietary NVIDIA driver the crash can persist (distro WebKit patch) — [#3654](https://github.com/block/buzz/issues/3654) stays open for that path. | | Blank window on any hardware, no crash output | Unknown GPU/driver combination | `--safe-rendering` flag (see below) | @@ -61,6 +62,29 @@ FONTCONFIG_FILE=~/.config/buzz-fontconfig/fonts.conf ./Buzz_*.AppImage --- +## Crash: `GStreamer element autoaudiosink not found` (AppImage) + +**Affected distributions:** Any distro missing GStreamer "good" plugins, and AppImage launches whose plugin search path does not include the host GStreamer dirs (Arch/Fedora under `/usr/lib/gstreamer-1.0`). + +**Symptom:** Buzz starts, the window stays blank, and the terminal shows `GStreamer element autoaudiosink not found` followed by WebKitWebProcess `SIGABRT`. + +**Root cause:** The AppImage strips bundled GStreamer and uses the host's. WebKitGTK RELEASE_ASSERTs when it cannot create an audio sink. `autoaudiosink` is provided by gst-plugins-good. linuxdeploy's AppRun also force-sets `GST_PLUGIN_SYSTEM_PATH_1_0` to an empty in-bundle directory, which *replaces* GStreamer's default search path — so even an installed host plugin set is invisible until the launcher shim points at host dirs. + +**Fix:** Install the GStreamer good plugins, then relaunch: + +```bash +# Arch +sudo pacman -S gst-plugins-good +# Debian/Ubuntu +sudo apt install gstreamer1.0-plugins-good +``` + +AppImage builds include a launcher shim (`desktop/scripts/fix-appimage.sh`) that unsets bundle-pointing `GST_PLUGIN_*` overrides and sets `GST_PLUGIN_SYSTEM_PATH_1_0` to existing host plugin directories (`/usr/lib/gstreamer-1.0`, `/usr/lib64/gstreamer-1.0`, `/usr/lib/x86_64-linux-gnu/gstreamer-1.0`). Upgrade to an AppImage that includes that shim if an older build still reports missing plugins after the packages are installed. + +This is not a GPU/compositor failure — `--safe-rendering` will not recover a missing `autoaudiosink`. + +--- + ## Blank window on startup (no crash): dmabuf renderer **Affected hardware:** NVIDIA GPUs (proprietary and nouveau drivers) and AppImage installs on any GPU. Issue [#2338](https://github.com/block/buzz/issues/2338).