block / block/berd

Linux AppImage: WebKitWebProcess SIGABRT in createAudioSink — GST_PLUGIN_SYSTEM_PATH points at missing plugin dirs

Open
#195 2 comments 0 reactions 0 assignees View on GitHub
Dominant language
TypeScript
Stars
909
Forks
116
Avg merge
1d 1h
Merged PRs (30d)
156

Description

## Summary

Berd 0.6.2's Linux AppImage aborts `WebKitWebProcess` (`SIGABRT` / `SI_TKILL`) a few seconds after first launch. The UI process stays up, so the window goes blank rather than the whole app disappearing.

This is the same packaging hole Buzz already diagnosed and fixed in [block/buzz#2176](https://github.com/block/buzz/pull/2176). Berd did not get that shim.

## Environment

- Berd 0.6.2 extracted AppImage (`~/.local/opt/berd/squashfs-root`)
- OS: Omarchy 4.0.0 (Arch Linux)
- Session: Hyprland / Wayland; `GDK_BACKEND=x11` (linuxdeploy GTK hook)
- GPU: NVIDIA GeForce RTX 3060 Ti, driver 610.57.04
- Host GStreamer: 1.28.6 (`gst-plugins-base` installed)
- Bundled WebKitGTK 4.1 GNU build-id `2594e661ffa45aa2a47f83c2f2f10caaec9e273f`

Not an OOM: ~9 GiB free, no oom-kill in the journal.

## What happens

1. Launch Berd (`gtk-launch Berd.desktop`).
2. First-load renderer boots (`[renderer] renderer booted (first load this install)`).
3. ~8s later `WebKitWebProcess` calls `abort()`. systemd-coredump records it.
4. Main `Berd` process keeps running (ACP/npm install, goose serve). No replacement web process is spawned.

Reproduced twice on this machine (PIDs 116183 at 12:02 and 119514 at 12:11 NZST, 2026-08-25). Same abort offsets both times.

## Abort site (from the core)

`WTFCrashWithInfo` in:

- file: `Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.cpp`
- function: `GstElement *WebCore::MediaPlayerPrivateGStreamer::createAudioSink()`
- line: 1585

That is `RELEASE_ASSERT(audioSink)` after `createPlatformAudioSink("video")` returned NULL. The crashing thread still held the role string `"video"`.

WebKit's binary also contains `GStreamer element %s not found. Please install it`.

## Root cause

linuxdeploy's `AppRun.wrapped` force-sets:

```
GST_PLUGIN_SYSTEM_PATH=$APPDIR/usr/lib/gstreamer:$GST_PLUGIN_SYSTEM_PATH
GST_PLUGIN_SYSTEM_PATH_1_0=$APPDIR/usr/lib/gstreamer-1.0:$GST_PLUGIN_SYSTEM_PATH_1_0
```

A **set** `GST_PLUGIN_SYSTEM_PATH_1_0` **replaces** GStreamer's compiled-in default search path. Those two directories do not exist in the Berd AppImage. Berd ships GStreamer *libraries* (`libgstreamer-1.0.so.0`, `libgstaudio-1.0.so.0`, …) but no plugin tree.

At the crash second, GStreamer wrote `~/.cache/gstreamer-1.0/registry.x86_64.bin` — 76 bytes, version `1.23.90`, **zero plugins**.

Berd's launcher (`~/.local/bin/Berd`) only sets `WEBKIT_DMABUF_RENDERER_FORCE_SHM=1` on NVIDIA. It does not undo the GST override. There is no equivalent of Buzz's `usr/bin/buzz-desktop` GST shim.

This is not the NVIDIA DMA-BUF protocol crash. `WEBKIT_DMABUF_RENDERER_FORCE_SHM=1` was already set.

## Expected

Missing audio sink should fail the media element, not `abort()` the renderer. The AppImage should either ship GStreamer plugins or not replace the host plugin path (Buzz #2176).

## Suggested fix

Port Buzz's `desktop/scripts/fix-appimage.sh` shim: after `AppRun.wrapped` rewrites `GST_PLUGIN_*`, drop values that point into `$APPDIR` so host GStreamer can resolve `autoaudiosink` / `appsink` / `appsrc`. Alternatively ship a real `usr/lib/gstreamer-1.0` plugin set built against the bundled GStreamer.

Also worth a private `GST_REGISTRY` under `~/.local/share/xyz.block.berd/` so the AppImage does not clobber the desktop-wide registry (see [block/buzz#2560](https://github.com/block/buzz/issues/2560)).

## Related

- Same abort, same WebKit build-id, on Buzz AppImage on this machine (filing separately).
- Not [block/buzz#2338](https://github.com/block/buzz/issues/2338) (DMA-BUF).
- Not [block/buzz#6339](https://github.com/block/buzz/issues/6339) (Ubuntu `.deb` + system webkit 2.52.3).

Contributor guide

Open the contributing guide

Research direction

Start by locating how Berd generates AppRun.wrapped and its Linux launcher, then read Buzz's desktop/scripts/fix-appimage.sh referenced in the issue. Reproduce or inspect the GST_PLUGIN_SYSTEM_PATH values in an extracted AppImage. Done means the AppImage no longer replaces the host plugin path with missing $APPDIR directories, allowing the required GStreamer elements to resolve without the renderer aborting.

Written by the indexing model from the issue text.

Assessment

Tech stack
linux, shell
Domain
build-system, desktop
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
68/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.