Skip to content

[M1-DET-02] Fix macOS/Windows CI: replay test fopen C4996; exact tick count under frame budget 1 - #37

Merged
offdev merged 1 commit into
masterfrom
fix/ci-replay-record-tests
Sep 16, 2026
Merged

offdev merged 1 commit into
masterfrom
fix/ci-replay-record-tests

Conversation

@offdev

@offdev offdev commented Sep 16, 2026

Copy link
Copy Markdown
Owner

Context

The M1-DET-02 merge (544a8a4) reds the two non-Linux P0 jobs on master — both in the new tests/laige-sim/replay_record_tests.cpp:

Job Failure Root cause
Windows x64 (MSVC 2022) error C2220 at replay_record_tests.cpp(246) — build fails three plain std::fopen call sites → C4996 (deprecated), fatal under the engine's /WX policy
macOS arm64 + Intel ReplayEngine.RecordsEmptyFramesPerTick — stats().ticks = 9–10 and log.frames.size() = 9–10 where 8 is expected the 8-tick bounded run used the default frame budget (5); the run_headless contract (engine.h) allows a late frame to complete up to frameBudgetTicks - 1 ticks over the target — on the macOS runners a paced sleep overshoots a 16.67 ms tick interval, so a frame caught up 2 ticks (the per-tick frame invariant itself held: 9 frames for 9 ticks, 10 for 10)

Fix

  1. Windows — portable openReplayFile() using _fsopen(path, mode, _SH_DENYNO) on MSVC, plain fopen elsewhere: the identical pattern already verified on Windows CI by logging_tests.cpp and src/laige-sim/replay.cpp (plain-fopen sharing semantics — fopen_s/_SH_SECURE would deny a same-process read-only re-open).
  2. macOS — the same 8-tick bounded run now uses frame budget 1, the EngineRun.BoundedRunCompletesExactlyWithSystems precedent (engine_tests.cpp): each frame runs at most one tick, so a late frame drops its extra due tick instead of overshooting, and the run lands exactly on 8 under any cadence. The exact-count assertions are then contract-deterministic on every platform.

Verification

  • Local (g++ 16.2, Debug — the linux-gcc job's configuration): warning-free build, ctest 57/57, the fixed test repeated 3× at exactly ticks=8 (133 ms each).
  • The PR carries the ci:macos label, so the macOS arm64 + Intel jobs run on this PR. The Windows job runs on the merge (its fix is the already-Windows-verified _fsopen pattern).

… count under frame budget 1

The M1-DET-02 merge (544a8a4) went red on the two non-Linux P0 jobs,
both in the new tests/laige-sim/replay_record_tests.cpp:

- Windows x64 (MSVC 2022): three plain std::fopen call sites (the
  RoundTripBytes and EncodingIsDeterministic raw-file reads) are
  C4996 (deprecated), fatal under the engine's /WX policy. Follow the
  logging_tests.cpp / src/laige-sim/replay.cpp precedent: a portable
  openReplayFile using _fsopen(path, mode, _SH_DENYNO) on MSVC (plain-
  fopen sharing semantics — fopen_s/_SH_SECURE would deny a same-
  process read-only re-open) and std::fopen elsewhere.

- macOS arm64 + Intel: ReplayEngine.RecordsEmptyFramesPerTick ran the
  8-tick bounded run with the default frame budget (kDefaultMaxCatchUp
  Ticks = 5). The run_headless contract (engine.h) allows the final
  count to overshoot by up to frameBudgetTicks - 1 when a late frame
  catches up several due ticks at once — on the macOS runners a paced
  sleep overshoots a 16.67 ms tick interval, so the run completed 9-10
  ticks and the exact-count assertions (stats().ticks == 8,
  log.frames.size() == 8) failed, even though the frames-per-tick
  invariant itself held (9 frames for 9 ticks, 10 for 10). Run the
  same 8-tick bounded run with frame budget 1, the
  EngineRun.BoundedRunCompletesExactly precedent (engine_tests.cpp):
  each frame runs at most one tick, so the run lands exactly on 8
  under any cadence (a late frame drops, it does not overshoot) and
  the exact assertions are contract-deterministic on every platform.

Verified locally (g++ 16.2 Debug, the linux-gcc job's configuration):
warning-free build, ctest 57/57, and the fixed test repeated 3x at
exactly ticks=8 (133 ms each). The macOS job itself is verified by the
PR's ci:macos label; the Windows job runs on the merge (its fix is the
identical, already-Windows-verified _fsopen pattern).
@offdev
offdev merged commit b075ca1 into master Sep 16, 2026
11 checks passed
offdev added a commit that referenced this pull request Sep 17, 2026
…tion; crash-handler write() under Release -Werror (#42)

macOS (Intel + arm64) jobs:

samples/hello/hello-baseline.cpp:179 — std::min(emitted, baseline_.size()) mixes std::uint64_t with std::size_t. On macOS uint64_t is unsigned long long and size_t is unsigned long, so the template deduction is a hard AppleClang error. On Linux/Windows the two types alias, which is why every other P0 job compiled the same source. Fix: cast the size_t operand to uint64_t so both arguments are one type on every platform.

Determinism check job:

src/laige-core/logging.cpp:500 — (void)write(...) does not suppress glibc's warn_unused_result (the attribute is attached under fortification, i.e. optimized builds), and the engine's -Werror makes it fatal. That is why only the job's Release g++ tree (build-det-release) failed while Debug g++ and every clang tree compiled the same TU. Fix: consume the result — the crash notice is best-effort and there is no async-signal-safe fallback if the write fails (LOG-007).

Verification (local: g++ 16.2.1 / clang++ 22.1.8, x86-64 Linux):
- logging.cpp compiles clean under -Wall -Werror in Debug, Release, and Release+_FORTIFY_SOURCE=2 (the CI trigger); hello sample TUs clean under all four compiler/flag sets.
- Full ctest: 82/82 (incl. hello_baseline_fpx/fp32 + the mismatch/truncated/malformed/missing fixtures, replay and detcheck suites).
- The CI detcheck flow reproduced end to end: four targeted builds (g++ Debug, clang++ Debug, clang++ Debug+ASan, g++ Release), reference-baseline sanity on both backends, synthetic self-check, and pairs A (g++ Debug vs clang++ Debug) and B (ASan Debug vs Release) on both backends — all result=OK ticks=301.
- The macOS deduction error cannot be reproduced off-AppleClang (uint64_t == size_t on Linux/Windows); the P0 macOS jobs are the regression guard for it, as for the prior macOS CI fixes (#33, #35, #37, #39).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant