Skip to content

feat!: port the core FFI tree to Zig 0.16.0 - #305

Merged
hyperpolymath merged 3 commits into
mainfrom
feat/zig-016-core
Aug 7, 2026
Merged

feat!: port the core FFI tree to Zig 0.16.0#305
hyperpolymath merged 3 commits into
mainfrom
feat/zig-016-core

Conversation

@hyperpolymath

Copy link
Copy Markdown
Owner

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.zig is now byte-identical to the registry's template copy and owns the 0.16 compat layer — 0.16 removed std.Thread.Mutex, std.time.*Timestamp, std.time.Timer, std.crypto.random and std.posix.getenv outright:

Removed Shim replacement
std.Thread.Mutex shim.Mutex over std.Io.Mutex
std.time.{nano,milli,}Timestamp, Timer shim.*Timestamp / the Io clock
std.crypto.random.* shim.randomBytes / shim.randomInt
std.posix.getenv shim.getenv
shim.io(): one process-wide std.Io.Threaded

The three ports that weren't mechanical

  • loader.zigstd.fs.Filestd.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 silently. Caught by its own tests. Also realpathrealPathFile (returns a length now).
  • federation.zigstd.netstd.Io.net; socket+bind fuse into IpAddress.bind. Non-blocking recv is receiveTimeout with a zero Io.Clock.Duration on the .awake clock — a true MSG_DONTWAIT equivalent (confirmed by reading Io/Threaded.zig: it issues recvmsg(MSG_DONTWAIT) first and only then polls). SO_REUSEADDR is droppedBindOptions has 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 need SO_REUSEPORT).
  • verisimdb.zigprocess.Child.runstd.process.run, Term tags lowercased. The old term.Exited access would panic on a signal-killed child; the new switch returns the same error instead.

Pins

.tool-versions 0.15.1 → 0.16.0 and every setup-zig pin → 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.

Verification

  • cd ffi/zig && zig build test316/316 tests across 41 steps
  • E2E fixture cartridge → 17/17
  • All 26 workflows YAML-parse

Beyond 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

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>
@gitar-bot

gitar-bot Bot commented Aug 7, 2026

Copy link
Copy Markdown

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.
Learn more

Code Review ✅ Approved 2 resolved / 2 findings

Ports 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.

Auto-approved and auto-merge armed: No blocking issues found.
Please see Auto-approve Docs for details on setting custom approval criteria. — merges when pipeline and required approvals pass.

✅ 2 resolved
Edge Case: hashFile loop can spin on non-terminal 0-byte reads

📄 ffi/zig/src/loader.zig:76-85
The rewritten read loop treats only error.EndOfStream as terminal and, by the author's own comment, a 0-byte readStreaming return is non-terminal. For a regular file this is fine, but if a non-regular path (FIFO/pipe/char device) is ever passed, readStreaming can return 0 without EndOfStream and the while (true) loop busy-spins forever, hanging the caller. Practically low risk since cartridge paths are regular .so files, but a defensive guard (e.g. break/yield after a run of consecutive 0-byte reads, or reject non-regular files via stat before hashing) would make it robust.

Performance: Every mutex lock now routes through a lazily-built Io thread pool

📄 ffi/zig/src/cartridge_shim.zig:114-128
shim.Mutex.lock/unlock call io() on every acquisition, and the first call anywhere constructs a process-wide std.Io.Threaded (a thread pool backed by smp_allocator) that is never deinitialized. For hot lock paths (per-packet federation processing, catalogue mount/unmount) this adds an atomic acquire-load plus Io-interface dispatch per lock versus a direct futex, and pins a thread pool for the process lifetime. Functionally fine and the leak is acceptable for a singleton, but if lock contention or per-op latency matters, consider caching the std.Io handle once rather than re-resolving it on each lock/unlock.

Options

Display: compact → Showing less information.

Comment with these commands to change the behavior for this request:

Compact
gitar display:verbose         

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

Comment thread ffi/zig/src/loader.zig
Comment thread ffi/zig/src/cartridge_shim.zig
gitar-bot[bot]

This comment was marked as resolved.

@gitar-bot
gitar-bot Bot enabled auto-merge (squash) August 7, 2026 11:34
@gitar-bot gitar-bot Bot added the gitar-approved Added by Gitar label Aug 7, 2026
gitar-bot[bot]
gitar-bot Bot previously approved these changes Aug 7, 2026

@gitar-bot gitar-bot Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Gitar has auto-approved this PR and enabled auto-merge (configure)

@gitar-bot
gitar-bot Bot dismissed their stale review August 7, 2026 14:41

✅ All code review findings resolved.

Configure merge blocking

@hyperpolymath
hyperpolymath disabled auto-merge August 7, 2026 14:46
@hyperpolymath
hyperpolymath merged commit 79fc8a8 into main Aug 7, 2026
@hyperpolymath
hyperpolymath deleted the feat/zig-016-core branch August 7, 2026 14:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

gitar-approved Added by Gitar

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant