libtest runs each test on a thread with the default 2 MiB stack. In a debug
build, Device::new() materialises ~301 KiB of struct literals on the stack,
and postcard::from_bytes::<Device> rebuilds the whole value on the stack, so
any Device-constructing unit test (netplay savestate round trips etc.) peaks
at several times that and aborts the ENTIRE test binary with a stack
overflow, taking every other test down with it.
Fix, both layers:
- src/test_util.rs: with_big_stack() runs a test body on an explicitly sized
8 MiB thread (the budget the project already standardises on in
.cargo/config.toml). Regression test: a device serialise/restore/clone
round trip measured to overflow the 2 MiB libtest thread (SIGABRT) and
pass at 8 MiB, plus a size_of::<Device>() < 700 KiB tripwire.
- scripts/gate.sh: export RUST_MIN_STACK=8388608 around step 3 so the
documented gate also covers Device-constructing tests that are not yet
wrapped (the netplay cluster's !15/!18 tests land after this fix).
Verified: cargo test --lib bare (no env) -> 1 passed; full gate -> GATE_OK
with step 3 reporting 1 passed (was 0 on main).
gopher64-netplay has no runnable gate (#23), blocking !10!11!15!18. The
build cannot run on the review box -- seven Rust worktrees took C: to 0.3%
free. Gitea 1.22.6's runner API endpoints 404, so runner availability, its
accepted labels, and its image contents are all unknown; this reports them
before the real SDL3/LLVM/submodule workflow is written against guesses.
Finding 1: the Rust side calls on_netplay_resume_session,
on_netplay_save_session and set_netplay_is_host on AppWindow, but the
callbacks/property were only declared on the NetplayCreate/NetplayWait
sub-components. appwindow.slint now declares callback
netplay_resume_session(string), callback netplay_save_session and the
in-out property netplay_is_host <=> NetplayWaitData.is_host, and
forwards them at the NetplayCreate/NetplayWait instantiation sites,
matching the existing netplay callback pattern.
Finding 2: rfd::AsyncFilePicker does not exist in rfd 0.17; the crate
exports AsyncFileDialog (already used by this repo in src/ui/gui.rs).
Switch the resume file picker to rfd::AsyncFileDialog and use
FileHandle::path() for the display path.
Finding 3: set is_host from the ResponseSession lobby update instead of
at wait-window open, comparing the local player name against players[0]
(the session creator, always registered first). Re-evaluates on every
lobby update.
Issue #20: !17 (#16) made the x86-64-v3 baseline opt-in via RUSTFLAGS but
nothing set it, so release binaries silently fell back to the plain x86-64
baseline. Set RUSTFLAGS per matrix row on the two x86_64 entries only:
- linux x86_64-unknown-linux-gnu: -C target-cpu=x86-64-v3
- windows x86_64-pc-windows-msvc: -C target-cpu=x86-64-v3
-C link-arg=/STACK:8388608 (carries the 8 MB stack link-arg that the
repo config supplies for Windows, because RUSTFLAGS REPLACES config
rustflags rather than appending)
The aarch64 rows keep the config's link-args untouched (no RUSTFLAGS at
all), and macOS / android jobs plus .cargo/config.toml are unchanged.
Closes#20
Windows clones default to core.autocrlf=true, which checks out CRLF into
*.sh working copies even though the committed blobs are byte-clean. The
shebang then dies with "env: 'bash\r': No such file or directory"
(exit 127), which read like a broken script rather than a line-ending
artifact. Assert LF for all shell scripts at the repo root so every
Windows clone gets clean scripts/gate.sh, data/icon/generate.sh and
data/shader/output.sh.
Closes#19
Review findings addressed (PR #17 bounce):
1. gate.sh put the provisioned cmake/ninja on PATH but never added their
OWN lib root to LD_LIBRARY_PATH, so cmake died with exit 127
(librhash.so.0 / libuv.so.1 / libjsoncpp.so.25 not found) and cmake-rs
misreported 'is cmake not installed?'. The LLVM_BIN2 block now exports
LD_LIBRARY_PATH=~/local-tools/root/usr/lib/x86_64-linux-gnu (same
append pattern as the other two roots; final value carries all three).
2. The gate was compile-only. It now runs three steps: cargo check
--all-targets (type-check), cargo test --no-run (LINK every test
binary), cargo test --lib (EXECUTE headless lib unit tests).
3. docs/build-gate.md: prerequisites list the provisioned cmake's
shared-lib root, the test-execution decision record, and the new
troubleshooting entry.
Verified on the review box: cold full gate exits 0 (GATE_OK), step 1
check then 11m52s test-link codegen then 'running 0 tests / ok' (main has
no #[test] fns yet; the inbound netplay PRs add ~38); warm re-run 5.6s.
Two blockers fixed in .cargo/config.toml plus a documented gate script:
- target-cpu=x86-64-v3 (AVX2-only) is now opt-in — the default build is
portable; on Sandy Bridge (x86-64-v2) it miscompiled build scripts
(num-traits SIGABRT, 648518346341351440-byte allocation).
- AR=llvm-ar dropped (GNU ar is fine); CC=clang/CXX=clang++ retained
because build.rs needs clang for -flto=thin, resolved via PATH.
scripts/gate.sh records the review-box command: init submodules, wire the
user-local LLVM-18 / pkgconf / fontconfig-X11 roots (no sudo available),
then cargo check --all-targets. docs/build-gate.md explains the failure
modes. Verified: ./scripts/gate.sh exits 0 end-to-end on this box.
Add message-name constants and reliable-channel helpers for netplay
session state transfer:
- Message-name constants: netplay_state, netplay_state_ready,
resync_state, resync_ready
- Chunked message codec (encode_message_chunks / decode_message /
decode_packets) reusing the existing 16 KiB reliable-channel
transport; send_message/process_reliable_messages refactored onto it
- send_netplay_state / receive_netplay_state for full session state
- send_ready / wait_for_ready ack helpers (10s timeout, same pattern
as receive_message); receive_message extracted to wait_for_message
with preserve of input_delay/disconnect side effects
- Large payloads (>1MB) accumulate into incoming_message until a full
postcard message parses
- Unit tests: 5MB payload round-trip through the chunked codec, ack
send/receive within timeout, missing ack times out with the standard
panic pattern
Closes#1