The post-merge valgrind job on dev hangs. Root cause: the CI valgrind step
exports FASTSYNC_UNDER_VALGRIND=1, but nothing read it, and the
/proc/self/maps "vgpreload" probe is unreliable on valgrind 3.22 (the guest's
maps no longer list the tool's own libraries). So the fork-based unit tests
ran under valgrind anyway; tests that call io_set_fds() left the thread-local
read/write descriptors pointing at a closed test pipe, and a later
send_n_data()/receive_n_data() call was silently redirected to those stale fds
(legacy_session() prefers the globals, which the stdin/stdout SSH server
requires). Later tests only worked by fd-reuse luck; under valgrind the fd
numbers no longer coincide, so the read blocked forever on an empty pipe.
- test_utils.h: honor FASTSYNC_UNDER_VALGRIND (already set by ci.yaml) and keep
the maps scan as a best-effort fallback. Reset io_set_fds(-1, -1) at the
start of every RUN_TEST so one suite cannot leak descriptor redirection into
the next.
- test_iconv.c: skip the forking wire-string roundtrip under valgrind like the
other fork-based tests.
- config.c: initialize per_dir_filter_count in config_set_defaults. The field
was never initialized, so -F/-FF counting read uninitialized heap (valgrind:
conditional jump on uninitialised value at client_cli.c:1464) and could count
from garbage.
Verified with the CI-equivalent command (FASTSYNC_UNDER_VALGRIND=1 valgrind
--leak-check=full --show-leak-kinds=definite --error-exitcode=1): completes
with 0 errors (previously hung >80 min). Unit 43/43; full integration 729
passed; cppcheck and clang-format clean.