Repository navigation
Config reload freezes Ghostty indefinitely when the IO mailbox is full #14833
Description
Discussed in #14825
Originally posted by realfresh October 24, 2026
Issue Description
I came across this issue as I'm building a Ghostty theming application that allows you to live preview your colour, font, and other UI-related changes directly against your running Ghostty instance.
As I was running this app, since it often reloads to preview config edits live, my instance was also running Herdr, which sends 258 colour queries (OSC 10, OSC 11, and OSC 4 for every palette index) after each mode 2031 report and each resize.
From the source, I believe this is what happens:
- The io thread handles
change_config(Thread.zig:321). StreamHandler.changeConfigsendscolor_scheme_reportinto the io thread's own mailbox (stream_handler.zig:133). This happens even when mode 2031 is off.- The mailbox holds 64 messages (mailbox.zig:15). When it is full,
sendwaits forever (mailbox.zig:95). The io thread is the only reader of that mailbox, so it waits on itself. - Every query reply from io-reader is also a mailbox message, so a burst of queries keeps the mailbox full. After that, the main thread blocks on its next send to the same mailbox: the next reload, or the mouse entering the window.
The code is the same on main at 8ef0ec1. This looks like a regression from #9705, which moved this report from the
surface mailbox to the io mailbox. In 1.2.3, changeConfig still sent it with surfaceMessageWriter. #14245 is a similar hang on a full mailbox, but on the surface-free path, and #14444 does not change this one.
With osc-color-report-format = none, the Herdr case stopped freezing (no freeze in 885 reloads, against freezes after about 180 and 270 without it), which fits: colour queries then get no reply.
AI disclosure: I used Claude Code to investigate this. It read the Ghostty source, wrote the reproduction and drafted this report. I ran the reproduction myself and edited the report.
Expected Behavior
A config reload never freezes Ghostty.
Actual Behavior
Within a few seconds the terminal stops updating. Ghostty then stops responding and needs a force quit. A sample of the hung process (release build, so Ghostty frames are inlined) shows all three threads waiting on a futex:
Thread: main-thread
closure #1 in AppDelegate.setupSignals()
Thread.Futex.Deadline.wait
Thread: io
Thread.Futex.Deadline.wait
Thread: io-reader
Thread.Futex.Deadline.wait
The log agrees: the second reload is the last thing Ghostty logs, and none of the 27 SIGUSR2 sent over the next 5 seconds appears (log below).
Reproduction Steps
-
Open Ghostty and run this in it. It writes cursor position queries without pause and reads the replies:
stty raw -echo; cat >/dev/null & q=$(printf '\e[6n%.0s' {1..2000}); while :; do printf %s "$q"; done
-
From another terminal app, reload Ghostty's config repeatedly:
while :; do kill -USR2 $(pgrep -nx ghostty); sleep 0.15; done
-
Ghostty freezes within a few seconds. It froze in 5 of 5 runs.
Neither step alone freezes it. A reload with no config change is enough.
Ghostty Logs
# log stream --level debug during the repro, trimmed to the reloads
13:23:28.960 [ghostty] reloading configuration in response to SIGUSR2
13:23:28.961 [ghostty] config change notification
13:23:28.961 [ghostty] config change notification
13:23:29.121 [ghostty] reloading configuration in response to SIGUSR2
13:23:29.123 [ghostty] config change notification
13:23:29.123 [ghostty] config change notification
# nothing more is logged
Ghostty Version
Ghostty 1.3.1
Version
- version: 1.3.1
- channel: stable
Build Config
- Zig version : 0.15.2
- build mode : .ReleaseFast
- app runtime : .none
- font engine : .coretext
- renderer : renderer.generic.Renderer(renderer.Metal)
- libxev : kqueue
OS Version Information
macOS 27.0.1 (26A434)
(Linux only) Display Server
None
(Linux only) Desktop Environment/Window Manager
No response
Minimal Ghostty Configuration
None needed. Reproduced with --config-default-files=false.Additional Relevant Configuration
Herdr 0.9.5 triggered it in real use. The repro above does not need it.
I acknowledge that:
- I have reviewed the FAQ and confirm that my issue is NOT among them.
- I have searched the Ghostty documentation and confirm there doesn't exist a configuration option that solves my issue.
- I have searched the Ghostty repository (both open and closed Discussions and Issues) and confirm this is not a duplicate of an existing issue or discussion.
- I have checked the "Preview" tab on all text fields to ensure that everything looks right, and have wrapped all configuration and code in code blocks with a group of three backticks (
```) on separate lines.
Activity
termio: send the config change color scheme report directly
termio: send the config change color scheme report directly (#14834)