Skip to content

ghostty: renderer thread SIGSEGV/SIGBUS in fontconfig — vendored font libs collide with system libs (missing -fsys=) #548

Closed

Description

@jerem

Summary

ghostty-1.3.1-2.fc44 crashes in the renderer thread several times a day with SIGSEGV/SIGBUS inside fontconfig. The cause is a packaging issue rather than an upstream ghostty bug: the spec BuildRequires:/Requires: fontconfig, freetype and harfbuzz but never passes the corresponding -fsys= flags to zig build, so zig statically vendors its own copies and exports their symbols from the executable, while GTK4 separately pulls in the system libraries. Both end up live in the same address space.

[  637.888670] traps: renderer[11055] general protection fault ip:5561cf2671ba sp:7fdc8f7e1b10 error:0 in ghostty[1b271ba,5561cea8f000+b36000]
[  881.848338] renderer[11951]: segfault at 7fafdcab5080 ip 00005581fdbba198 sp 00007faf857d5b10 error 4 in ghostty[1b27198,5581fd3e2000+b36000]

Evidence

/usr/bin/ghostty links the system libs and exports the vendored copies' symbols:

$ ldd /usr/bin/ghostty | grep -E 'fontconfig|freetype|harfbuzz'
	libharfbuzz.so.0 => /lib64/libharfbuzz.so.0
	libfontconfig.so.1 => /lib64/libfontconfig.so.1
	libfreetype.so.6 => /lib64/libfreetype.so.6

$ for p in Fc FT_ hb_; do echo "$p: $(nm -D --defined-only /usr/bin/ghostty | grep -cE " [TWD] $p")"; done
Fc: 27
FT_: 57
hb_: 518

The executable wins global symbol resolution, so calls from libgtk-4, pango and cairo to those 602 entry points get interposed into ghostty's vendored copies while the data they operate on came from the system libraries.

Two fontconfigs are demonstrably live at once. The system is fontconfig 2.17.0 (FC_CACHE_VERSION_NUMBER 9); the vendored copy is a cache-8 vintage. A core dump has both generations mapped simultaneously:

$ grep -oE 'cache-[0-9]+' maps.txt | sort | uniq -c
     49 cache-8      # vendored
     50 cache-9      # system 2.17.0

The race

Teardown side — GTK reinitializes fontconfig on a settings change, and the call lands in the vendored copy (note the zig builddir path):

#0  FcRefIsConst () at .../zig/p/N-V-.../src/fcatomic.h:169     <-- SIGBUS
#1  FcPatternDestroy () at .../src/fcpat.c:430
#2  FcFontSetDestroy () at .../src/fcfs.c:50
#3  FcConfigDestroy (config=0x55802363ffa0) at .../src/fccfg.c:388
#4  FcConfigSetCurrent () at .../src/fccfg.c:583
#5  FcInitReinitialize () at .../src/fcinit.c:221
#6  gtk_settings_notify.lto_priv () at /lib64/libgtk-4.so.1

That destroys the config's font sets and munmaps the cache files it held.

Consumer side — meanwhile the renderer thread is walking that same config for a fallback glyph:

#0  FcCompare (pat=0x7faf48180f20, fnt=0x7fafdcab5080, ...) at .../src/fcmatch.c:622   <-- SIGSEGV
#1  FcFontSetSort () at .../src/fcmatch.c:1273
#2  FcFontSort () at .../src/fcmatch.c:1399
#3  config.Config.fontSort () at pkg/fontconfig/config.zig:27
#4  font.discovery.Fontconfig.discover () at src/font/discovery.zig:271
#5  font.discovery.Fontconfig.discoverFallback () at src/font/discovery.zig:292
#6  font.CodepointResolver.getIndex (cp=22823, style=regular) at src/font/CodepointResolver.zig:175
#7  font.SharedGrid.getIndex (cp=22823) at src/font/SharedGrid.zig:180
#8  font.shaper.run.RunIterator.indexForCell () at src/font/shaper/run.zig:340
...
#10 renderer.generic.Renderer(renderer.OpenGL).rebuildRow () at src/renderer/generic.zig:2972
#12 renderer.generic.Renderer(renderer.OpenGL).updateFrame () at src/renderer/generic.zig:1364
#21 renderer.Thread.threadMain () at src/renderer/Thread.zig:201

The faulting fnt pointer sits in a one-page hole between two live cache mappings — memory that was unmapped out from under it:

0x7fafdca59000-0x7fafdcab5000  d63f98f1…-le64.cache-9
        <hole — one page, fault at 0x7fafdcab5080>
0x7fafdcab6000-0x7fafdcab9000  a11fef9c…-le64.cache-8

cp=22823 is U+5927 (大), i.e. any codepoint that needs fallback discovery can trigger it. In practice CJK or emoji in the terminal plus any event that makes GTK bump gtk-fontconfig-timestamp.

Fix

Pass the -fsys= flags the spec's existing BuildRequires already imply. PR attached. With it:

1.3.1-2 patched
exported Fc* 27 0
exported FT_* 57 0
exported hb_* 518 0

The rebuilt binary imports 18 Fc* / 35 FT_* / 15 hb_* from /lib64 instead, so there is exactly one of each library in the process. bzip2-devel is added as a BuildRequires because -fsys=freetype makes SharedDeps.zig:152 call linkSystemLibrary2("bzip2"), which needs bzip2.pc.

I've built and installed this locally and confirmed the symbol collision is gone; I can't yet claim a long-term crash-free soak, but the mechanism above is no longer possible with a single fontconfig in the process.

Unrelated heads-up

BuildRequires: zig now resolves to zig 0.16.0 on Fedora 44, while ghostty 1.3.1 declares minimum_zig_version = "0.15.2" in build.zig.zon. I had to build with an upstream 0.15.2 tarball. A rebuild of the current spec may need a pinned zig.

Environment

  • Fedora 44, kernel 7.1.8-200.fc44.x86_64, GNOME/Wayland
  • ghostty-1.3.1-2.fc44.x86_64 from copr:scottames:ghostty
  • fontconfig-2.17.0-4.fc44, freetype-2.14.3-1.fc44, harfbuzz (F44), gtk4-4.22.4

Activity

  1. jerem commented on Aug 11, 2026

    @jerem
    ContributorAuthor

    Cross-reference: #476 already proposed -fsys=fontconfig for this a month before I opened this issue, with independent confirmation from @kapuchai in that thread. I missed it — my PR #549 is closed as a duplicate.

    Per @scottames there, the fix is blocked on Zig packaging: ghostty 1.3.1 requires Zig 0.15.x exactly (src/build/zig.zig:9-11 compares major and minor for equality), and Fedora 44 now ships 0.16.0, so BuildRequires: zig can't currently satisfy this spec. The plan there is to wait for ghostty-org/ghostty#12228 in the next Ghostty release.

    Keeping this open only for the part #476 doesn't cover — that freetype (57 symbols) and harfbuzz (518) are vendored and exported alongside fontconfig's 27, so -fsys=fontconfig on its own leaves the same interposition hazard in the other two. Details on #476. Close this if you'd rather track everything on the PR.

  2. added a commit that references this issue on Aug 12, 2026
    f1711f1
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions