Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 34 additions & 13 deletions desktop/scripts/fix-appimage.sh
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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 --
Expand Down Expand Up @@ -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).
Expand Down Expand Up @@ -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 \
Expand All @@ -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"
Expand Down
24 changes: 24 additions & 0 deletions docs/linux-rendering-troubleshooting.md
Original file line number Diff line number Diff line change
Expand Up @@ -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) |

Expand Down Expand Up @@ -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).
Expand Down