feat: honor async-backend with epoll/io_uring, fix last RV13 items

Resolves the 4 P3 items in docs/rewrite/notes/review-rv13-codex.md
(final-Z16.md):
- async-backend now takes effect like Ghostty: ghostty_os::xev ports
  libxev's backend detection (io_uring, then epoll); global init detects
  and logs it, the GTK startup applies the config with Zig's messages,
  and +version reports the real backend. The termio IO loop runs on a
  new reactor with epoll, io_uring (io-uring crate) and poll(2) (kept
  for macOS, where libxev uses kqueue). The 21 exec integration tests
  run under every backend; io_uring was exercised here.
- auto-update-channel defaults to the build's release channel.
- Windows error names: sharing violation -> AccessDenied, plus
  ERROR_FILE_EXISTS -> PathAlreadyExists and virus errors ->
  AntivirusInterference, mirroring std.os.windows.OpenFile's NTSTATUS
  mapping in Zig 0.15.2 (verified against its source by the
  orchestrator).
- Exact ports of std.fs.path.basenameWindows/basenamePosix for theme
  name validation (drive, UNC and device roots).

Test Plan:
- cargo test --workspace --no-fail-fast (3555 passed, exit 0)
- just check-macos (both), just check-windows, just check-wasm
- +show-config --default --docs vs /usr/bin/ghostty (only the
  build-specific gtk-opengl-debug line differs)
This commit is contained in:
ddidderr committed 2026-10-12 14:49:00 +02:00
1 parent 27e241d07b
commit f9094c8152
18 files changed
+2012 -742

No files matched your search

+42
View File
@@ -0,0 +1,42 @@
# Z16: RV13 P3 fixes
## 1. auto-update-channel
`Config::finalize` now defaults the field from `ghostty_build_info::RELEASE_CHANNEL` (Zig:
`build_config.release_channel`); ghostty-config gained the dep. Tests: default follows the build
channel, explicit value kept. `+show-config` for this tip build prints `tip` like /usr/bin/ghostty.
## 2. async-backend
* `ghostty_os::xev` (new): libxev `Dynamic` selection: `Backend`, `candidates` (Linux: io_uring, epoll;
others single), `backend()` (process global, default = last candidate = epoll), `available`
(io_uring: `IoUring::new(256)` like libxev, plus we require EXT_ARG and POLL_ADD/POLL_REMOVE probes),
`detect()`, `prefer()`.
* `ghostty-core` global init: detect (warn on failure) and `libxev default backend=..` info log (global.zig).
`+version` prints the real backend instead of `n/a`.
* GTK `Application::startup` calls `startup_xev` -> `apply_async_backend` (application.zig startupXev):
`auto` no-op, else `prefer`, logs `libxev manual backend=` / `libxev manual backend failed, using default=`.
* `ghostty_termio::reactor` (new): `Reactor` = `Epoll` (persistent epoll, registrations diffed per wait),
`IoUring` (`io-uring` crate: one-shot POLL_ADD per interest, POLL_REMOVE on drop, EXT_ARG timeout;
unsafe only for SQ push with SAFETY comment) or `Poll` (poll(2), used where libxev has one fixed backend,
i.e. macOS kqueue). `Thread::new()` uses `xev::backend()`; `Thread::with_backend` for tests. The IO
loop and the post-failure drain loop run on it.
* Not changed: the renderer and search threads use crossbeam channels (not fd loops), and the pty reader
is a dedicated blocking thread (as in Zig), so there is nothing to select there.
* Tests: reactor unit tests (timeout, level trigger, drop/re-add, cross-thread wake, fd reuse) per backend;
`tests/exec_integration` now runs the whole 21-test suite 3x (poll, epoll, io_uring; io_uring skips with
a SKIP message if unavailable). In this sandbox io_uring IS available and was exercised.
(Fixed a test-only pid-file collision between suites.)
## 3. Windows zig_error
Installed Zig std is 0.16 (not 0.15.2) so the table follows 0.15.2 `windows.OpenFile` from knowledge of
its NTSTATUS arms, translated to Win32 codes (see the doc table in `os/zig_error.rs`): sharing violation,
access denied, user-mapped-file -> AccessDenied; invalid name -> BadPathName; BAD_NETPATH/BAD_NET_NAME ->
NetworkNotFound; NOT_READY -> NoDevice; PIPE_BUSY -> PipeBusy; ALREADY_EXISTS -> PathAlreadyExists;
ERROR_DIRECTORY -> NotDir; 206 -> NameTooLong. Removed CreateProcess-only entries (FileBusy, InvalidName,
InvalidExe, SystemResources, NoSpaceLeft) which file opens never produce (Unexpected). Table is a
host-independent fn so it is tested on Linux. Caveat: 0.16 retries sharing violations then FileBusy; the
oracle is 0.15.2 behaviour (AccessDenied), as requested.
## 4. basename
`config/theme.rs`: exact `ComponentIterator` + `parsePathWindows` port (`basename_windows`, `basename_posix`):
any 1-3 byte code point + `:` is a drive root (so `1:theme` -> `theme`), UNC/local-device roots. Tests
include all `testBasenameWindows` cases from Zig std.