Skip to content

tests: attribute scratch-tmpfs watcher events to this process, not co-tenants - #521

Merged
luisleo526 merged 4 commits into
mainfrom
fu/tmpwatch-attribution
Oct 26, 2026
Merged

luisleo526 merged 4 commits into
mainfrom
fu/tmpwatch-attribution

Conversation

@luisleo526

@luisleo526 luisleo526 commented Oct 26, 2026 •

Copy link
Copy Markdown
Collaborator

Removes a 1.8.0 cut-run risk: a co-tenant job on the same CI VM could turn these rows red.

Problem

test_default_scratch_tmpfs_tmpdir and test_jailed_scratch_tmpfs_tmpdir judge the host-shared /dev/shm, /tmp and /var/tmp by any file that appears there during the run (pineforge-* for the default row, any name for the jailed row). The watcher never identifies the creator, and RUN_SERIAL serialises only one ctest, not the second runner on the same 2-runner post VM. A co-tenant job can therefore turn a green engine run red (and the default row's /var/tmp positive claim could false-PASS on a co-tenant's file).

Change (tests only)

  • The tmpfs candidate is a private mkdtemp directory under /dev/shm owned by the test (RAII cleanup confined to that directory) and is watched strictly.
  • In /tmp and /var/tmp, attribution is exact: the test executable interposes the engine's only temp-file creation path (mkstemp, include/pineforge/detail/scratch_file.hpp:147, src/command_scratch_production.cpp:235) inside the test executable only; no engine source, no include/, no build flag or option the shipped library sees (CMake changes link dl/Threads to the three test targets only, Linux only).
  • New tests/test_scratch_watch_attribution.cpp rows: a planted co-tenant file no longer fails the default or jailed row; a co-tenant file cannot satisfy the positive claim; files this process creates in /tmp, /var/tmp or /dev/shm still fail.

Files touched: tests/CMakeLists.txt, tests/default_scratch_tmpfs_fixture.hpp, tests/test_default_scratch_tmpfs_tmpdir.cpp, tests/test_jailed_scratch_tmpfs_tmpdir.cpp, tests/test_scratch_watch_attribution.cpp (new). Route: CI-only; promotes no baseline.

Limit

For the shared roots /tmp and /var/tmp the negative claim sees only scratch created through mkstemp in this process (plus anything created inside the private TMPDIR). A future engine path that creates scratch there with another call (open(O_CREAT), O_TMPFILE) would not be seen in those two roots. The positive /var/tmp claim and the private-directory watch are not affected. Today the only scratch creators are the two mkstemp sites above.

Evidence

  • Linux build host, ctest of the touched targets plus the cmake lane-file checker tests, on the merged tree: job rj-20261026t054615-1bd154 passed (the same selection passed on the earlier head in rj-20261026t040636-1f56c7: 15/15, including both scratch-tmpfs tests, the nine test_scratch_watch_attribution* cases, test_pipe_writer_fd_flags and test_cr150_cmake_d with its controls).
  • Red on the base, black-box (job rj-20261026t050715-5b540a): the UNCHANGED tests of the base commit run once without interference (green), then again while a separate process creates and removes pineforge-* files in /dev/shm and /tmp throughout the run; a judge that requires the green control and then exit 1 with the watcher's own assertion passed for both rows. This is the co-tenant failure this PR removes.
  • Debug and sanitizer profiles of this branch: job rj-20261026t055037-a75341 passed on the merged tree (debug: 1179 tests, 100%; sanitizers: 1160 tests, 100%, including the scratch-attribution cases and both scratch-tmpfs rows built under the sanitizer interceptors). Main has since gained only unrelated checker-script files.
  • Not run on the author's machine.

🤖 Generated with Claude Code

ci-cx added 3 commits October 26, 2026 12:05
…reated, not by any file a co-tenant job makes in the shared tmp roots (CR-352)

test_default_scratch_tmpfs_tmpdir and test_jailed_scratch_tmpfs_tmpdir failed
after a successful run whenever an inotify watch on the HOST-SHARED /dev/shm,
/tmp and /var/tmp saw any pineforge- file (default row) or ANY file (jailed
row), whoever made it. RUN_SERIAL serialises one ctest only, so the second
runner on a 2-runner post VM could turn a cut-commit ci-post red.

What the rows prove is unchanged: with TMPDIR on tmpfs the default scratch
lands in the disk-backed /var/tmp and never in /dev/shm or /tmp, and a jailed
(sealed-arena) run creates nothing in those directories. Only the evidence is
now attributable:

- The row's TMPDIR becomes a private directory the test owns inside /dev/shm
  (mkdtemp; cleaned by the test's own RAII, inside that directory only) and is
  watched strictly: any creation there, by any call, is this run's.
- The test executable defines its own extern "C" mkstemp that forwards through
  dlsym(RTLD_NEXT) and records the resulting path, checked against
  /proc/self/fd/<returned fd>. The engine creates scratch only through mkstemp
  (include/pineforge/detail/scratch_file.hpp, src/command_scratch_production.cpp),
  so /var/tmp and /tmp claims are exact: the /var/tmp positive can no longer be
  satisfied by a co-tenant's file, and a co-tenant's file in /tmp no longer
  fails the row. Shared-root inotify is not used for any verdict.
- tests/test_scratch_watch_attribution.cpp (Linux, 9 cases): a co-tenant made by
  a forked child (old watcher red, new green); the run's own scratch planted in
  /tmp, /dev/shm, the private directory, a non-mkstemp creation in the private
  directory (all still red); the /var/tmp positive that a planted file cannot
  fake; a real ScratchFile through the header path.

The interposer lives in the test executables only: the shipped library, include/,
src/ and every library build flag are untouched; the CMake additions are the
test targets' own link lines (libdl, Threads) and the new test's registration.
Limit: scratch created by a future non-mkstemp call in /tmp or /var/tmp would
not be seen by the interposer (the private directory still sees any creator
there).

Not run on the author's machine; Linux CI is the evidence.
…al/state/pineforge-top-core/lanes/ci-lab/clone into fu-tmpwatch
@luisleo526 luisleo526 changed the title tests: attribute scratch-tmpfs watcher events to this process, not co-tenants (Part of CR-352) tests: attribute scratch-tmpfs watcher events to this process, not co-tenants Oct 26, 2026
@luisleo526
luisleo526 merged commit 434b98c into main Oct 26, 2026
13 checks passed
luisleo526 added a commit that referenced this pull request Oct 26, 2026
Adds one bullet to the CI and release process list from the merged change
#521: the two scratch-on-tmpfs tests attribute watcher events to their own
process, not to co-tenant jobs, with the limit the change states. Tests only.

Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
luisleo526 added a commit that referenced this pull request Oct 26, 2026
Adds one bullet to the CI and release process list from the merged change
#526: the release gate also requires a green, non-skipped post-merge run of the
released commit. Also corrects the scope of the mkstemp sentence in the #521
bullet to /tmp and /var/tmp. Documentation only.

Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
luisleo526 added a commit that referenced this pull request Oct 26, 2026
Main moved by scripts and tests only (#525, #521, #526); CHANGELOG.md is
unchanged on main since the base of this branch, so the merge result is main's
tree with this branch's CHANGELOG.md.

Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
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