Why
All tests that call setup_temp_directory_for_signer share the same base path:
mithril_test/tests_setup/mithril_crypto_helper_material/{party_id}
KES key files in this shared directory are written non-atomically: to_file first calls fs::File::create, which truncates the file to empty, and then writes the JSON content in a second step.
A concurrent test that reads the file between those two steps sees an empty file and panics with:
EOF while parsing a value at line 1 column 0
The result is that some CI runs fail this test due to race conditions (see, for example, this one on an unrelated part of the code base)
What
The test certificate_chain::certificate_verifier::tests::verify_genesis_certificate_fails_if_is_not_genesis, and potentially any other test that reads KES key files from the shared temp directory, fails intermittently when the Hydra runner executes tests in parallel.
Rerunning the job succeeds, masking the underlying data race.
How
Why
All tests that call
setup_temp_directory_for_signershare the same base path:KES key files in this shared directory are written non-atomically:
to_filefirst callsfs::File::create, which truncates the file to empty, and then writes the JSON content in a second step.A concurrent test that reads the file between those two steps sees an empty file and panics with:
The result is that some CI runs fail this test due to race conditions (see, for example, this one on an unrelated part of the code base)
What
The test
certificate_chain::certificate_verifier::tests::verify_genesis_certificate_fails_if_is_not_genesis, and potentially any other test that reads KES key files from the shared temp directory, fails intermittently when the Hydra runner executes tests in parallel.Rerunning the job succeeds, masking the underlying data race.
How
fixture_builder.rs, replace the directto_filecalls forkes.skandopcert.certwith a write-to-temp-then-rename pattern.std::process::id()or a random suffix in the temp filename to avoid collisions between parallel processes.fs::renameis atomic on POSIX filesystems, so concurrent readers will always see either no file or a complete one.to_filethat write into a shared temp directory.