Repository navigation
Description
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_: 518The 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.0The 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_64fromcopr:scottames:ghosttyfontconfig-2.17.0-4.fc44,freetype-2.14.3-1.fc44,harfbuzz(F44),gtk4-4.22.4
Activity
jerem commentedon Aug 11, 2026
Cross-reference: #476 already proposed
-fsys=fontconfigfor 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-11compares major and minor for equality), and Fedora 44 now ships 0.16.0, soBuildRequires: zigcan'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=fontconfigon 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.fix(ghostty): build against system fontconfig/freetype/harfbuzz (#549)