Skip to content

scripts: make three silent tooling failures loud - #137

Merged
martinus merged 1 commit into
masterfrom
tooling/scratch-and-profile-guards
Jul 25, 2026
Merged

scripts: make three silent tooling failures loud#137
martinus merged 1 commit into
masterfrom
tooling/scratch-and-profile-guards

Conversation

@martinus

Copy link
Copy Markdown
Owner

Three tooling bugs, all hit during the #134 work. What they have in common is that each one failed in a way that looked like success — no error, or an error nobody sees.

1. verify.sh silently stops when the scratch is tmpfs

The valgrind smoke takes its scratch from ${DUPEREMOVE_TEST_DIR:-${TMPDIR:-/tmp}}. With the variable unset — the documented default — make check still passes, because the integration harness independently defaults to .itest-scratch next to the repo. But the smoke lands in /tmp, which is tmpfs on most distros. oans correctly refuses to dedupe there and exits 1 — and its message went straight into the smoke's >/dev/null.

The result: the script stopped mid-step with no output at all. My first v1.5.0 release attempt looked like it had simply ended, and the | tail I'd piped it through hid the non-zero exit too.

Now it checks the scratch filesystem before doing anything:

=== valgrind smoke (scan + dedupe + bare replay) ===
verify: scratch '/tmp/verify-smoke.UoZAK4' is on 'tmpfs', but the valgrind smoke
        deduplicates and needs btrfs or xfs. Point DUPEREMOVE_TEST_DIR
        at a reflink-capable directory, e.g.:
            DUPEREMOVE_TEST_DIR=$HOME/.itest-scratch scripts/verify.sh

and the smoke retains its output, so any other failure explains itself instead of vanishing.

2. perf-profile.sh --cold was refused on machines that support it

It probed sudo -n true. But the sensible sudoers rule to grant is exactly tee /proc/sys/vm/drop_caches and nothing else — which is what scripts/bench.py already relies on — and under such a rule sudo -n true still demands a password.

So --cold was disabled on precisely the boxes configured for it, while bench.py dropped caches happily. It now probes the real command.

3. perf-profile.sh profiled upstream duperemove by default

Binary resolution was ./duperemove, then PATH — never ./oans, which is what this repo builds. And since make install puts a duperemove compatibility symlink on PATH, a bare invocation cheerfully profiled the installed upstream duperemove 0.15.2, reporting it in the header where it reads as perfectly normal. My first profile of the O(n²) hotspot was of upstream, not the fork.

It now prefers ./oans, and warns before falling back:

perf-profile: warning: no ./oans or ./duperemove in /tmp;
              profiling /usr/bin/duperemove, which is probably NOT your build.
              Build first, or pass -b/--binary explicitly.

This is the same trap CLAUDE.md already warns about in prose ("Confirm you're testing this ./oans, not a system duperemove") — now enforced by the script rather than left to the reader.

Verification

Each fix exercised against the failure it addresses:

  • verify.sh with DUPEREMOVE_TEST_DIR unset → exits 1, names the tmpfs and the fix (previously: silent stop).
  • --cold → completes and records a real profile (previously: bailed on the sudo probe).
  • bare perf-profile.sh in the repo → binary : ./oans (previously: /usr/bin/duperemove).
  • bare run from a directory with no build → prints the fallback warning, then proceeds.
  • scripts/verify.sh passes end to end.

All three cost a wasted run during the #134 work, and each failed in a way
that looked like success.

verify.sh: the valgrind smoke picks its scratch from
${DUPEREMOVE_TEST_DIR:-${TMPDIR:-/tmp}}. With the variable unset - the
documented default - `make check` still passes, because the integration
harness defaults to .itest-scratch next to the repo, but the smoke lands in
/tmp, which is tmpfs on most distros. oans correctly refuses to dedupe there
and exits 1, except its message went to the smoke's `>/dev/null`, so the
script stopped mid-step with no output whatsoever. It now checks the scratch
filesystem up front and says what to set, and the smoke keeps its output so a
failure explains itself.

perf-profile.sh --cold probed `sudo -n true`, but the sensible sudoers rule
to grant is exactly `tee /proc/sys/vm/drop_caches` and nothing else - which
is what scripts/bench.py relies on - and under that rule `sudo -n true` still
demands a password. So --cold was refused on precisely the machines set up to
support it. It now probes the real command.

perf-profile.sh also resolved its binary as ./duperemove then PATH, never
./oans. Since `make install` puts a `duperemove` compatibility symlink on
PATH, a bare invocation happily profiled the installed *upstream* duperemove
0.15.2 instead of the local build, and reported it in the header where it
reads as normal. It now prefers ./oans and warns loudly when it falls all the
way back to PATH.

Verified each: verify.sh with DUPEREMOVE_TEST_DIR unset now exits 1 naming
the tmpfs and the fix; --cold completes and records a real profile; a bare
run reports `binary : ./oans`; and from a directory with no build it prints
the fallback warning before profiling.

Co-Authored-By: Claude <noreply@anthropic.com>
@martinus
martinus merged commit 8a97205 into master Jul 25, 2026
15 of 16 checks passed
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