Split out of #7144, which found it: the temp-hygiene gate added there compiles the
census corpus with TMPDIR pointed at an empty directory, and the directory is not
empty afterwards — but the leftovers are not the clang driver's.
What happens
run_pipeline.rs creates a per-invocation object staging directory:
// crates/perry/src/commands/compile/run_pipeline.rs
let object_output_dir = {
let dir = std::env::temp_dir().join(format!("perry-objs-{}-{}", std::process::id(), nanos));
std::fs::create_dir_all(&dir)?;
dir
};
and removes it on the two link exits (executable, shared library):
if !args.keep_intermediates {
for obj_path in &obj_cleanup_paths { let _ = fs::remove_file(obj_path); }
let _ = fs::remove_dir(&object_output_dir);
}
--no-link returns at if args.no_link { before either, so the directory and every
object in it stay. There is no third cleanup site.
Measured
54 --no-link --no-cache compiles of the 27-workload census corpus, with TMPDIR
isolated to a fresh directory:
108 entries left behind — one perry-objs-<pid>-<nanos>/ directory and one .o per compile
perry-objs-41179-1785566532368471000/fixture_ptr_shape_ts.o
perry-objs-41180-1785566685697174000/fixture_ptr_shape_sites_ts.o
…
Unlike #7144 this is unbounded in the number of compiles, not in distinct IR:
the directory name carries pid + wall-clock nanos, so every invocation leaks a fresh
one. Objects are also much larger than the .lls were.
Who hits it
Every --no-link user: perry compile --no-link, the separate-link workflow, and
every harness in scripts/compiler_output_harness/ (the census, knob isolation and
determinism gates all pass --no-link).
Detection already in place
scripts/compiler_output_regression.py census-temp-hygiene (added in #7144) reports
these under "Not this gate's subject" and does not fail on them, deliberately —
a gate that goes red for another module's defect gets muted rather than fixed. When
this is fixed, widen OWNED_PREFIXES in
scripts/compiler_output_harness/repsel_temp_hygiene.py so the gate asserts the
temp directory is empty outright; the comment there says so.
Note
The fix is not "add a third remove_dir" so much as "have one exit that cleans up".
Three call sites that must each remember is how the third one came to be missing.
Split out of #7144, which found it: the temp-hygiene gate added there compiles the
census corpus with
TMPDIRpointed at an empty directory, and the directory is notempty afterwards — but the leftovers are not the clang driver's.
What happens
run_pipeline.rscreates a per-invocation object staging directory:and removes it on the two link exits (executable, shared library):
--no-linkreturns atif args.no_link {before either, so the directory and everyobject in it stay. There is no third cleanup site.
Measured
54
--no-link --no-cachecompiles of the 27-workload census corpus, withTMPDIRisolated to a fresh directory:
Unlike #7144 this is unbounded in the number of compiles, not in distinct IR:
the directory name carries pid + wall-clock nanos, so every invocation leaks a fresh
one. Objects are also much larger than the
.lls were.Who hits it
Every
--no-linkuser:perry compile --no-link, the separate-link workflow, andevery harness in
scripts/compiler_output_harness/(the census, knob isolation anddeterminism gates all pass
--no-link).Detection already in place
scripts/compiler_output_regression.py census-temp-hygiene(added in #7144) reportsthese under "Not this gate's subject" and does not fail on them, deliberately —
a gate that goes red for another module's defect gets muted rather than fixed. When
this is fixed, widen
OWNED_PREFIXESinscripts/compiler_output_harness/repsel_temp_hygiene.pyso the gate asserts thetemp directory is empty outright; the comment there says so.
Note
The fix is not "add a third
remove_dir" so much as "have one exit that cleans up".Three call sites that must each remember is how the third one came to be missing.