What happened
On PR #907, CI run 34073019835 (Linux runner, Rust tests (mint)), the unit test audit::tests::rotation_seals_history_without_breaking_restart_or_verification failed:
panicked at crates/registry-mint/src/audit.rs:425:14:
audit restarts from the segmented tail: Audit(SinkLocked { path: "/tmp/.tmpZrWnSn/audit/mint.jsonl.lock" })
167 other tests passed. The previous CI run of the same PR, with identical registry-mint code, passed this job, and PR #907 does not touch registry-mint or registry-platform-audit. The failed job was rerun.
Suspected mechanism (inferred from the code, not yet reproduced)
The single-writer sink takes an flock on the sentinel <path>.lock (registry-platform-audit, acquire_writer_lock) and releases it when its File drops. flock belongs to the open file description, which a forked child shares until exec closes it through CLOEXEC.
secretfile::tests::a_fifo_is_refused_without_waiting_for_a_writer (added by #902) spawns mkfifo through std::process::Command in the same unit test binary. When that fork overlaps the rotation test's drop-then-initialize sequence, the child still holds the lock descriptor for the window between fork and exec, so the second MintAuditLog::initialize reports SinkLocked.
A reproduction would loop the two tests together in one process under load.
Options
- Create the fifo without forking (
libc::mkfifo or nix::unistd::mkfifo), so the unit test binary never forks. Preferred: it removes the window instead of hiding it.
- Move process-spawning tests out of the unit test binary into an integration test binary.
- Retry
initialize briefly in the rotation test. This hides the window rather than removing it, and it would weaken a test that pins the restart contract.
Any other unit test binary that both spawns processes and exercises the single-writer sink has the same exposure.
What happened
On PR #907, CI run 34073019835 (Linux runner,
Rust tests (mint)), the unit testaudit::tests::rotation_seals_history_without_breaking_restart_or_verificationfailed:167 other tests passed. The previous CI run of the same PR, with identical
registry-mintcode, passed this job, and PR #907 does not touchregistry-mintorregistry-platform-audit. The failed job was rerun.Suspected mechanism (inferred from the code, not yet reproduced)
The single-writer sink takes an
flockon the sentinel<path>.lock(registry-platform-audit,acquire_writer_lock) and releases it when itsFiledrops.flockbelongs to the open file description, which a forked child shares untilexeccloses it throughCLOEXEC.secretfile::tests::a_fifo_is_refused_without_waiting_for_a_writer(added by #902) spawnsmkfifothroughstd::process::Commandin the same unit test binary. When that fork overlaps the rotation test's drop-then-initializesequence, the child still holds the lock descriptor for the window between fork and exec, so the secondMintAuditLog::initializereportsSinkLocked.A reproduction would loop the two tests together in one process under load.
Options
libc::mkfifoornix::unistd::mkfifo), so the unit test binary never forks. Preferred: it removes the window instead of hiding it.initializebriefly in the rotation test. This hides the window rather than removing it, and it would weaken a test that pins the restart contract.Any other unit test binary that both spawns processes and exercises the single-writer sink has the same exposure.