CI runs only the jobs generate.py emits, so a config that falls out of the
matrix size it belongs to takes its coverage with it and fails nothing. Add
validate_linux_matrices(), called on every invocation, which checks that no two
configs expand to the same name, that minimal is part of full and full part of
extended, that each config reaches the sizes its flags ask for and no others,
and that the extended tier is not empty. The checks name no config, only the
flags, so adding or removing one needs no edit there. Reject a config declaring
both "minimal" and "extended", which the filtering would drop from the minimal
matrix, the opposite of what it asked for. Extract expand_linux_config() so the
checks and the matrix builder cannot disagree about what a config expands to.
The script never sees the event that triggered the run, so it cannot tell
whether this run should have asked for the extended configs at all, and a
condition that stops matching the events would drop them and fail nothing.
So move the three GENERATE_ variables to job level, where the generate step and
a new check read the same values, and have that check re-run the generator with
--extended and compare. It runs only on the events that must produce the
extended matrix.
Proved by mutation: seven edits to linux.json and to the filtering each fail,
and the message names the config that moved. The generated matrix is
byte-identical to the previous one across all seven argument combinations, so
the extraction changed no job.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
tsan.supp turned lock-order checking off wholesale: deadlock:pthread_create,
deadlock:pthread_rwlock_rdlock and deadlock:boost::asio name locking
primitives rather than source files, so between them they covered every
std::shared_mutex read lock and any inversion reached through a strand or a
thread start, and detect_deadlocks defaults to true. Seven more named source
files, among them ValidatorList.cpp, ValidatorSite.cpp and Manifest.cpp. Drop
all ten, because the job cannot fail a build, so a suppression here costs a
finding and buys nothing. The Manifest.cpp line alone was hiding a two-thread
deadlock between ManifestCache::save() and the validator list, which a run
without it reported 52 times on the shutdown path. Also repoint eight
patterns at files that moved into libxrpl and the gtest tree, and empty
sanitizer-ignorelist.txt of 24 entries that never matched anything, either
through suppression syntax a clang ignorelist never consults or through a
glob with no leading star. Both rules are now written down in
docs/build/sanitizers.md.
Add ubuntu-clang-debug-amd64-tsan to the Linux matrix, in a config of its
own so TSan stays on clang and Debug, and give the matrix a third tier so
it runs at night rather than on every labelled pull request. A Linux config
may now declare "extended", which holds it out of both the minimal and the
full matrix; generate.py emits those configs only for --extended, which the
workflow passes on a schedule or a manual run. The name says which matrix a
config belongs to, like "minimal", rather than naming a trigger, because the
trigger set already grew from the schedule to manual runs and a config
property outlives that. It avoids "maximal", which reads as a synonym for
the full matrix it is meant to be larger than. It is a whole hour of
runner time, which is too much to spend per pull request, and it reports
nothing back anyway, because the workflow appends exitcode=0 to
TSAN_OPTIONS. That belongs in the workflow rather than in
runtime-tsan-options.txt, which the documented local command also reads and
which must keep failing on a finding.
Cap the test jobs at 4 under TSan, which is measured rather than chosen.
One per core is 30 on the current runner and twice starved it until it lost
contact with the server; 12 was killed by the OOM killer with code 137
before a single suite finished; 4 completes the suite. The machine has 32
cores and no swap, so nothing absorbs the peak, and the runner is one pod
among several on a node, so the ceiling is not ours alone.
Check that a build carries the instrumentation it asked for, by the __asan,
__tsan and __ubsan symbols in the binary, since instrumented code
references its runtime however that runtime is linked. The version string
is checked too, but cannot stand alone, because cmake sets the SANITIZERS
macro separately from the flags. Widen the voidstar step for this rather
than add a second one, and add ASAN_ENABLED, TSAN_ENABLED and UBSAN_ENABLED
so a step needing one sanitizer does not parse the list. Define XRPL_ASAN,
XRPL_TSAN and XRPL_UBSAN so a test can skip when its sanitizer is inactive,
and drop the -Dcoverage_test_parallelism example from BUILD.md, which
neither cmake nor conanfile.py defines.
* upstream/release/3.3.x: (41 commits)
chore: Bump version to 3.3.0
chore: Bump version to 3.3.0-rc7
fix: Increase manifest protocol message size cap and fix manifests relay
fix: Cap untrusted manifests per message and drop oversized ones
chore: Bump version to 3.2.1
chore: Bump version to 3.2.1-rc1
fix: Cap untrusted manifests per message and drop oversized ones
fix: Reject oversized validator manifest before decoding
fix: Reduce untrusted manifest cache cap to 100
fix: Bound untrusted manifest cache
chore: Bump version to 3.3.0-rc6
feat: Package validator-keys inside rippled
chore: Bump version to 3.3.0-rc5
fix: Switch SponsorshipSet to use a delta for sfFeeAmount
fix: Re-revert "fix: Set request size limits and differential pricing for get-object-by-hash calls"
chore: Bump version to 3.3.0-rc4
fix: Revert "fix: Set request size limits and differential pricing for get-object-by-hash calls"
chore: Bump version to 3.3.0-rc3
fix: Reduce untrusted manifest cache cap to 100
fix: Revert "fix: Reject oversized SHAMap nodes in gotStaleData and fetch-pack path"
...