Skip to content

test: compare borrowed fd flags without Darwin's written bit (Part of CR-352) - #519

Merged
luisleo526 merged 3 commits into
mainfrom
fu/macosfd-fix
Oct 26, 2026
Merged

luisleo526 merged 3 commits into
mainfrom
fu/macosfd-fix

Conversation

@luisleo526

Copy link
Copy Markdown
Collaborator

Part of CR-352: fixes the three fd tests on macOS; test_kernel_residuals TvJO is fixed separately.

What this fixes

Engine main's macOS-26 legs have been red since the CR-150 merge (91353de, 10-25): test_report_nonfinite_equity_cabi_fd, test_report_nonfinite_equity_cpp_fd and test_report_sink_fd report that a borrowed pipe fd "changed". 1.7.0 was tagged over it; a green ci-post on the cut commit is a tag requirement for 1.8.0.

Cause (measured, not guessed)

A diagnostics run on macos-26 (run 40250032093, job 121339778730) added an engine-free control: a plain pipe, one 21-byte write by the test itself. The writer's F_GETFL went 0x1 -> 0x10001 at that write and stayed; F_GETFD never changed. The three engine tests show the same single bit (xor 0x10000) at their first write (C ABI "after strategy_native_run_v1", C++ "after fill_report", L22A "after run", i.e. before any NULL removal). The refusing iterations pass because the writer refuses before a byte reaches the pipe. So the engine does not change any caller-controlled flag of the borrowed fd; the tests' raw F_GETFL equality was wrong on Darwin. (That the bit is XNU's FWASWRITTEN, "descriptor was written", is read from the headers; CI proves only that a plain pipe write sets 0x10000 on macos-26.)

Change (tests only; no src/ or include/)

  • tests/fd_flag_diagnostics.hpp (new, shared by 4 tests): comparable_status_flags() clears exactly bit 0x00010000 on __APPLE__ (static_asserted to that value) and is the identity everywhere else; a failed query stays negative; same_flags() also refuses a failed F_GETFL. Failure messages print the raw F_GETFL and F_GETFD (queried separately, hex, errno, XOR), the fstat identity and the FIRST boundary at which the pair differs. Snapshots only call fcntl/fstat; nothing prints on success.
  • The three tests compare the masked F_GETFL on both sides in all four raw comparisons (C ABI final, C++ final, L22A final NULL removal, and the rejected-replacement comparison in test_report_sink_fd.cpp that the macOS run never reached). F_GETFD stays strictly equal. Every original condition is kept.
  • tests/test_pipe_writer_fd_flags.cpp + one CMake line (UNIX): the engine-free control on a plain and an F_DUPFD_CLOEXEC writer. On Apple the raw difference after the first write must be 0 or exactly that bit; on Linux the raw values must be equal. Controls that run on Linux show the helper does NOT hide a flip of O_NONBLOCK, O_APPEND, the access mode, FD_CLOEXEC, or a failed fcntl.

Evidence (proof run 40256257584 on this head, b883edb)

  • build (macos-26, Debug) job 121358699096: 100% tests passed out of 1128.
  • build (macos-26, Release) job 121358699121: 1186 of 1187 passed; test_pipe_writer_fd_flags, test_report_nonfinite_equity_cabi_fd / _cpp_fd, test_report_sink_fd and the other fd rows all Passed. The one failure is test_kernel_residuals ('TvJO' in the built archive), a separate cause with its own PR.

🤖 Generated with Claude Code

ci-cx added 3 commits October 26, 2026 08:26
…rowed-fd tests, plus an engine-free pipe control (CR-150 follow-up, diagnostics only)

Engine main's macOS-26 Debug leg has been red since the CR-150 merge
(test_report_nonfinite_equity_cabi_fd, test_report_nonfinite_equity_cpp_fd,
test_report_sink_fd): each says only that a borrowed pipe fd "changed".
A source read found no engine call that writes F_GETFL/F_GETFD on a borrowed
fd, and the assertions cannot tell which query differs, by which bit, or at
which step.

This change only adds information; no comparison is weakened or removed:

- tests/fd_flag_diagnostics.hpp: separate F_GETFL and F_GETFD queries (each
  with errno captured at once), fstat identity, boundary snapshots, and a
  failure message naming the baseline, final value, XOR and the first boundary
  that differs.
- The three tests keep every original condition (baseline validity, raw
  equality of both queries, the destruction check) and now take the final
  values from the same real fcntl calls; intermediate snapshots are
  observations only.
- tests/test_pipe_writer_fd_flags.cpp (new, UNIX): an engine-free plain and
  F_DUPFD_CLOEXEC writer pipe, reader non-blocking as in the nonfinite tests,
  writer flags compared strictly across one non-empty write, a drain and the
  reader's close. On macOS it shows whether Darwin pipe semantics or the
  engine change the flag.

No src/ or include/ change. Not run on macOS or locally; the branch CI
macOS-26 Debug leg is the evidence.
…as written" bit (CR-150 follow-up, fixes the three macOS-red tests)

macOS-26 Debug has been red on main since the CR-150 merge because
test_report_nonfinite_equity_cabi_fd, test_report_nonfinite_equity_cpp_fd and
test_report_sink_fd compare the raw F_GETFL of a borrowed pipe fd across a run.
The diagnostics run (engine-free control test_pipe_writer_fd_flags, no engine in
the process) showed that on macOS the first successful write to any pipe sets
bit 0x00010000 in the writer's F_GETFL (0x1 -> 0x10001), F_GETFD unchanged.
The engine does not change a caller-controlled flag; the assumption in the
tests is wrong on Darwin.

- tests/fd_flag_diagnostics.hpp: comparable_status_flags() clears exactly that
  one bit on __APPLE__ (FWASWRITTEN, static_asserted to 0x00010000) and is the
  identity everywhere else; a failed query stays negative. same_flags() now
  also refuses a failed F_GETFL on either side.
- The three tests (all raw F_GETFL equalities across a run, including the
  rejected-replacement comparison in test_report_sink_fd that the macOS run
  never reached) compare the masked value on both sides; F_GETFD stays strict;
  the failure messages still print the raw hex values.
- test_pipe_writer_fd_flags: on Apple the raw difference after the first write
  must be 0 or exactly that bit, on Linux the raw values must be equal; added
  Linux-running mutation controls showing the helper does not hide a change of
  O_NONBLOCK, O_APPEND, the access mode or FD_CLOEXEC, nor a failed fcntl.

No src/ or include/ change. Verified only by the branch CI (macOS-26 Debug).
@luisleo526
luisleo526 merged commit b7e16f5 into main Oct 26, 2026
13 checks passed
luisleo526 added a commit that referenced this pull request Oct 26, 2026
## What

Adds the `## 1.8.0 — 2026-10-27` section (with migration notes) to `CHANGELOG.md`, above `## 1.7.0`. `CHANGELOG.md` is the only file changed (+131/-0). Documentation only: no `src/`, `include/`, `docker/`, `scripts/`, `tests/` or workflow file is touched.

## Why

The engine release body is generated from git-log subjects only and carries no migration notes; the release notes users read are this file (and the GitHub release body edited from it after publish). The notes must be on main before the release dispatch.

## Content

- Compatibility and migration: exact pairing with codegen 1.8.0, regenerate C++ and relink every strategy library, no public header change, the new codegen `color` input type, the changed harness file `docker/run_json.py`.
- Faster `run_json` report handling (#517) with the measured table against 1.6.3 and 1.7.0 and the statement that the gap to 1.6.3 is not closed.
- Scratch placement restated (#518); the unused storage building block (#515; its allocation-gate sites are unreviewed, no bound claimed); a known limit (memory with never-filled pending orders, "a fix is planned for a later release").
- CI and release process: every merged change since 1.7.0 not listed above (#505-#510, #513, #514, #516, #519, #520, #522, #469, #481, #504). Every line is taken from the merged commit body; none claims a behaviour change for a tests-only or CI-only change.

Not in this commit (not on main at base `641349a`): the release gate, tmpwatch and the TvJO fix. Each gets one line from its merged PR body as a follow-up commit on this branch before this PR merges; this PR is meant to merge after those three.

## Checks

- Route: docs-only, `lab verify --via ci-only` (no sweep).
- Read as a committed diff by an independent reviewer: GO. All 18 engine commits `v1.7.0..641349a` have a bullet, none extra.
- Numbers: the #517 timings and RSS are the measurements in the #517 body; the ratios in the text were recomputed (1.77/0.36 = 4.9, 8.26/1.35 = 6.1, 8.94/5.39 = 1.66; 4.61/0.36 = 12.8, 22.31/1.35 = 16.5, 22.99/5.39 = 4.27).
- The heading date `2026-10-27` is the planned tag date and is corrected before the tag if the date moves.

🤖 Generated with [Claude Code](https://claude.com/claude-code)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant