CI / build-and-test (push) Failing after 38s
Gitea CI flagged two things on the last push: 1. A -Wunused-result warning on an intentionally-ignored write() return value in test_crash_consistency.c's progress side-channel. Fixed with an explicit (void) cast and a comment explaining why ignoring it is safe (a short write there only makes the progress count more conservative, per that function's own existing documented tolerance). 2. A real LeakSanitizer failure -- 256 bytes across 4 allocations from vfs_new/vfs_unmount. Root cause: tests/test_journal_failure.c's two "reopen after the failure, verify recovery" blocks called vfs_unmount/backend_free/backend_free inside their `if (ov2)` branch (the normal, expected path) but vfs_free(v2) only on the `else` branch, which is never actually reached in practice. Fixed by moving vfs_free(v2) to run unconditionally after the if, in both blocks. This bug was invisible locally across many runs because local sanitizer verification had been using ASAN_OPTIONS=detect_leaks=0 -- adopted originally for a real reason (a SIGKILLed forked child in test_crash_consistency.c never runs its own exit-time leak check, so its allocations were never the actual concern) but applied to the whole test run, which also suppressed detection of this real bug in the *parent* process's own code. CI doesn't set that option, so it caught what local runs couldn't. Documented in CONTRIBUTING.md as a real process gap, not just a code bug: a local verification habit that diverges from what CI actually runs can let a real finding through until it reaches CI. Verified: confirmed the leak directly first (reproduced locally by dropping the detect_leaks=0 override, matching CI exactly, before touching any code), then confirmed the fix by re-running the same no-override sweep across all 8 test binaries with zero leaks found, plus a clean make all + make test. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UqJpkdJ6Njnt1pw3CbghzB