fix(os,termio): FreeBSD support, dev-profile resource precedence, docs

Final fix pass per the stopping criterion (docs/rewrite/PLAN.md),
resolving the remaining RV18 build/behaviour items (final-Z21.md):
- termio errno access uses the per-target libc accessor (__error on
  FreeBSD/DragonFly/Apple, __errno on OpenBSD/NetBSD/Android) instead of
  __errno_location everywhere, unblocking non-Linux BSD builds.
- FreeBSD resource discovery follows Zig (site-terminfo, local/share).
- Zig's Debug-only resource precedence (and the dev workspace-resources
  fallback) key off a ghostty_debug_build cfg set from PROFILE=="debug"
  instead of debug_assertions, so release builds with assertions honor
  GHOSTTY_RESOURCES_DIR first like Zig ReleaseSafe.
- KNOWN_DIFFERENCES.md lists the remaining P3 differences deliberately
  left unfixed (theme-preview editing details, a cleanup timeout edge
  case) and what cannot be verified on this machine.
- DEVIANT_FIXES.md registers the PTY-hangup output drain (35), the
  canvas BGRA conversion (36) and the dev resources fallback.

Test Plan:
- cargo test --workspace --no-fail-fast (exit 0)
- cargo check --target x86_64-unknown-freebsd -p ghostty-os
This commit is contained in:
ddidderr committed 2026-10-12 16:53:27 +02:00
1 parent 729b544820
commit 7b59457cb8
6 files changed
+83 -7

No files matched your search

+3
View File
@@ -60,6 +60,8 @@ when this file was written.
| 32 | OS: URL opener child reaping | `os/open.zig` (`try collectOutput(...)` before `wait()`) | When collecting the opener's output fails (e.g. more than 50 KiB on a stream), the error returns before `wait()`, leaving the child as a zombie. | The child is always reaped; the collection error is still logged. | `4a55abf` fix-deviant(os) | `ghostty-os` open tests |
| 33 | OS: maximum-length `NOTIFY_SOCKET` | `os/systemd.zig:100-116` (`socket_address.path.len < socket_path.len`, then `path[socket_path.len] = 0`) | A 108-byte path (the size of `sockaddr_un.path`) passes the length check, and the terminating NUL is written at `path[108]`, one byte past the array (out-of-bounds write). Separate from row 13 (the abstract-socket `@` handling). | The address is built with rustix's `SocketAddrUnix::new`, which takes the 108 bytes without a terminator (valid for Linux `AF_UNIX`) and rejects longer paths; no out-of-bounds write. Verified in code. | f8c5ce0 (`git log -S` on `ghostty-os/src/systemd.rs`: the only commit touching it, besides formatting/macOS changes) | `notify_maximum_length_socket_path_is_rejected_safely` (`ghostty-os/src/systemd.rs`) |
| 34 | Renderer (Metal): buffer reallocation size | `renderer/metal/buffer.zig:89` (`Buffer.sync`) and `:146` (`syncFromArrayLists`) | `size = req_bytes * 2` is already in bytes, then `size * @sizeOf(T)` is passed to `newBufferWithLength:options:`, so the new buffer is `sizeof(T)` times larger than intended (GPU-memory over-allocation). | The new buffer is exactly `2 * req_bytes` (`metal_layout::grown_buffer_bytes`); the element count is `2 * total_len`. | bab49ee; registered + test in `2040677` fix-deviant(renderer) | `metal_layout::tests::grown_buffer_bytes_is_double_the_required_bytes_not_scaled_by_size_of_t` (runs on any host; the Metal buffer itself is compile-checked only) |
| 35 | Termio: PTY hangup drops unread output | `termio/Exec.zig` `ReadThread.threadMainPosix` (exits as soon as `POLL.HUP` is seen) | `POLLIN \| POLLHUP` can arrive together with unread final output (a Linux PTY check confirmed this); exiting immediately loses the tail of the child's output. | After HUP the read thread makes one more pass over the fd, so the remaining output is delivered before exit. | 6629fb0 | none (needs a live PTY; verified by RV18 on Linux) |
| 36 | Font (wasm/browser Canvas): atlas pixel format | `font/face/web_canvas.zig` (atlas write branch on `.rgba`) | The branch tests a stale `.rgba` format against an enum that contains `.bgra`, so BGRA atlases are never converted. | The BGRA atlas conversion is implemented. No claim of equivalence with a real browser (not testable here). | d89691b | `ghostty-font` web_canvas tests (compile/Node level) |
## Upstream quirks deliberately kept (not fixed)
@@ -100,6 +102,7 @@ Only entries with an observable behavioural difference are listed.
| OSC 52 base64 acceptance | Surface.zig:2149,2163 rules | Was different in both directions (Codex core audit); fixed to match Zig | `notes/review-core-codex.md` | 2f58f02 |
| Benchmark / synthetic tooling extensions | `ghostty-bench` has no `--time` option and only the simplified terminal handler; `ghostty-synthetic` has the actions `ascii`, `osc`, `utf8` | `ghostty-bench --time` prints the measured step time to stderr; `ghostty-bench --handler=full` runs the full `stream_readonly` handler instead of the print-only one; `ghostty-synthetic +sgr` generates SGR-heavy output. Dev/benchmark tooling only; otherwise upstream behaviour is unchanged | `crates/ghostty-bench/src/main.rs`, `src/benches.rs`, `src/bin/ghostty-synthetic.rs`; `notes/review-rv16-codex.md` | 0c4f0ee |
| Inspector font rasterizer (Windows, Apple, wasm) | Dear ImGui is built with `IMGUI_ENABLE_FREETYPE` (`pkg/dcimgui`), so the 32 px inspector font is rasterized by FreeType | Linux and other Unix targets: FreeType (`dear-imgui-rs` feature `freetype`, system FreeType through pkg-config), 32 px. Windows, Apple and wasm32 keep Dear ImGui's stb_truetype loader at 32 px, because `dear-imgui-sys` can only locate FreeType through pkg-config/vcpkg and those targets cannot be built or run here. Glyph anti-aliasing differs slightly there. | `crates/ghostty-inspector/Cargo.toml`, `src/inspector.rs` (`embedded_font_source`) | Z20 (uncommitted) |
| Development resources fallback | `resourcesDir` returns nothing when no terminfo bundle is found next to the binary | In the Cargo `dev` profile, if neither installed resources nor `GHOSTTY_RESOURCES_DIR` apply, the in-repo `<workspace>/resources` directory is used when the binary lives inside this workspace | `crates/ghostty-os/src/resourcesdir.rs` (`dev_resources_dir`) | 967e3a1 |
## Maintenance