feat!: port the core FFI tree to Zig 0.16.0 - #305
Conversation
Completes the toolchain convergence for boj-server's own Zig code, matching
the cartridge sweep in boj-server-cartridges#109.
The canonical shim (ffi/zig/src/cartridge_shim.zig) is now byte-identical to
the registry's template copy and owns the 0.16 compat layer: a lazily
initialised process-wide std.Io.Threaded exposed as shim.io(), shim.Mutex
over std.Io.Mutex, timestamp helpers over the Io clock, plus randomBytes /
randomInt / getenv. Zig 0.16 removed std.Thread.Mutex, std.time.*Timestamp,
std.time.Timer, std.crypto.random and std.posix.getenv outright.
Ported: catalogue, community, coprocessor, federation, guardian, loader,
sdp, sla, verisimdb, bench + the aspect/bench tests.
Notable non-mechanical work:
- loader.zig: std.fs.File -> std.Io.File. 0.16 signals end-of-stream with
error.EndOfStream; a 0-byte return no longer means EOF, so the hashFile
read loop would have spun or truncated. Also realpath -> realPathFile
(returns a length), and positional write/close via the io handle.
- federation.zig: std.net -> std.Io.net, and the socket/bind pair fuses
into IpAddress.bind. Non-blocking recv is now receiveTimeout with a
zero Io.Clock.Duration on the .awake clock — a true MSG_DONTWAIT
equivalent, verified by reading Io/Threaded.zig. SO_REUSEADDR is dropped:
BindOptions exposes no equivalent and the option is only meaningful
before bind, which is no longer a separate call. Harmless for unicast UDP.
- verisimdb.zig: process.Child.run -> std.process.run; Term tags lowercased.
- aspect_security_test.zig: std.io.fixedBufferStream -> std.Io.Writer.fixed.
The shim module now links libc (shim.getenv wraps std.c.getenv) and is wired
as a named build module so file-path and module imports cannot both pull it
into the graph.
Pins: .tool-versions 0.15.1 -> 0.16.0, and every setup-zig pin to 0.16.0.
The three archived goto-bus-stop/setup-zig uses (truthfulness, lsp-dap-bsp,
e2e) migrate to the mlugg action this repo already pins elsewhere.
Verified: `zig build test` in ffi/zig is 316/316 across 41 steps; the E2E
fixture cartridge is 17/17.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
Note Automatic reviews are paused because your trial's included automatic processing has been used for this period. Upgrade now, or comment "Gitar review" to run a review anytime. Code Review ✅ Approved 2 resolved / 2 findingsPorts the core FFI tree and toolchain to Zig 0.16.0 with updated file I/O, networking, and process management. Consider tightening the hashFile loop to handle non-terminal 0-byte reads and reviewing the lazy Io thread pool mutex routing.
✅ 2 resolved✅ Edge Case: hashFile loop can spin on non-terminal 0-byte reads
✅ Performance: Every mutex lock now routes through a lazily-built Io thread pool
OptionsDisplay: compact → Showing less information. Comment with these commands to change the behavior for this request:
Important Your trial ends in 3 days — upgrade now to keep code review, CI analysis, auto-apply, custom automations, and more. Was this helpful? React with 👍 / 👎 | Gitar |
✅ All code review findings resolved.
PR B of the BoJ 0.16 campaign
Completes the toolchain convergence for boj-server's own Zig code, matching the cartridge sweep in boj-server-cartridges#109.
The canonical shim
ffi/zig/src/cartridge_shim.zigis now byte-identical to the registry's template copy and owns the 0.16 compat layer — 0.16 removedstd.Thread.Mutex,std.time.*Timestamp,std.time.Timer,std.crypto.randomandstd.posix.getenvoutright:std.Thread.Mutexshim.Mutexoverstd.Io.Mutexstd.time.{nano,milli,}Timestamp,Timershim.*Timestamp/ the Io clockstd.crypto.random.*shim.randomBytes/shim.randomIntstd.posix.getenvshim.getenvshim.io(): one process-widestd.Io.ThreadedThe three ports that weren't mechanical
loader.zig—std.fs.File→std.Io.File. 0.16 signals end-of-stream witherror.EndOfStream; a 0-byte return no longer means EOF, so thehashFileread loop would have spun or truncated silently. Caught by its own tests. Alsorealpath→realPathFile(returns a length now).federation.zig—std.net→std.Io.net;socket+bindfuse intoIpAddress.bind. Non-blocking recv isreceiveTimeoutwith a zeroIo.Clock.Durationon the.awakeclock — a trueMSG_DONTWAITequivalent (confirmed by readingIo/Threaded.zig: it issuesrecvmsg(MSG_DONTWAIT)first and only then polls).SO_REUSEADDRis dropped —BindOptionshas no equivalent and the option is only meaningful before bind, which is no longer a separate call. Harmless for unicast UDP (no TIME_WAIT; port sharing would needSO_REUSEPORT).verisimdb.zig—process.Child.run→std.process.run,Termtags lowercased. The oldterm.Exitedaccess would panic on a signal-killed child; the newswitchreturns the same error instead.Pins
.tool-versions0.15.1 → 0.16.0 and everysetup-zigpin → 0.16.0. The three archivedgoto-bus-stop/setup-ziguses (truthfulness, lsp-dap-bsp, e2e) migrate to themluggaction this repo already pins elsewhere.Verification
cd ffi/zig && zig build test→ 316/316 tests across 41 stepsBeyond the suite, the federation receive path was exercised directly (loopback heartbeat received, sender address round-trips to the same peer slot, QUIC key-exchange tag) because its tests are defensively written and green alone wouldn't prove it.
🤖 Generated with Claude Code