Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .clangd
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,9 @@ InlayHints:
ParameterNames: No
DeducedTypes: Yes
Designators: No
# No background index: lint.sh runs several short-lived clangd processes
# back-to-back (clangd-tidy chunks), and a clangd starting while the previous
# one's index shards are mid-write crashes at startup (clangd-tidy aborts with
# "Invalid header end"). The lint runs don't benefit from the index anyway.
Index:
Background: Skip
6 changes: 6 additions & 0 deletions packages/streamr-dht/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -254,6 +254,12 @@ if(NOT IOS AND STREAMR_MODULES_SUPPORTED)
test/integration/ConnectionManagerIntegrationTest.cpp
test/integration/DhtNodeRpcRemoteTest.cpp
test/integration/RouterRpcRemoteTest.cpp
test/integration/MultipleEntryPointJoiningTest.cpp
test/integration/DhtNodeTest.cpp
test/integration/MockLayer1Layer0Test.cpp
test/integration/Layer1ScaleTest.cpp
test/integration/DhtNodeExternalApiTest.cpp
test/integration/KademliaCorrectnessTest.cpp
)

target_include_directories(streamr-dht-test-integration
Expand Down
44 changes: 42 additions & 2 deletions packages/streamr-dht/lint.sh
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,48 @@ echo "Running clangd-tidy on $FILES"
# false positive through the StoreRpcRemote / StoreManager coroutine
# cluster; the compiler builds and runs both, clang-format still checks
# them. (LocalDataStoreTest.cpp does NOT trip it.)
TIDY_FILES=$(echo "$FILES" | tr ' ' '\n' | grep -v 'test/integration/ConnectionLockingTest.cpp' | grep -v 'test/unit/PendingConnectionTest.cpp' | grep -v 'test/unit/SimulatorTest.cpp' | grep -v 'test/integration/SimultaneousConnectionsTest.cpp' | grep -v 'test/integration/ConnectionManagerIntegrationTest.cpp' | grep -v 'test/unit/DhtNodeRpcLocalTest.cpp' | grep -v 'test/integration/DhtNodeRpcRemoteTest.cpp' | grep -v 'test/unit/RoutingSessionTest.cpp' | grep -v 'test/unit/RecursiveOperationSessionTest.cpp' | grep -v 'test/unit/StoreRpcLocalTest.cpp' | grep -v 'test/unit/StoreManagerTest.cpp' | tr '\n' ' ')
clangd-tidy -p "$COMPILE_DB" $TIDY_FILES
# MultipleEntryPointJoiningTest.cpp (phase A8) trips the same false
# positive through the DhtNode import set (a spurious "no matching
# constructor" for the branded ServiceID inside the included
# DhtNodeTestUtils.hpp); the compiler builds and runs it, and the OTHER
# A8 tests including the same header pass clangd — the variance is the
# hallmark of the std-type unification issue. clang-format still checks it.
# DhtNodeTestUtils.hpp (phase A8) is a plain header whose names come from
# module imports done by the INCLUDING test (a module wrapping DhtNode's
# interface exhausts clang's source locations, so it cannot be a module —
# see the header comment); standalone clangd has no imports to resolve it
# against, so every name errors (and processing it standalone can crash
# clangd, aborting the whole batch). The including tests are clangd-tidied
# and the compiler builds it on every platform; clang-format still checks
# it.
# The full-node integration tests (phase A8) each import the DhtNode
# aggregate, whose BMI merge consumes most of clang's per-TU
# source-location space (see module-sloc-dedup-plan.md); clangd does not
# fully release that space between files, so batching several of them into
# ONE clangd process exhausts it and kills clangd mid-session (clangd-tidy
# aborts with "Invalid header end"). They lint clean individually, so each
# gets its own clangd process below. (DhtNodeTest.cpp is excluded outright
# instead: it trips the std-type unification false positive — gtest's own
# CodeLocation/MakeAndRegisterTestInfo reported ambiguous — like the other
# excluded files; the compiler builds and runs it on every platform and
# clang-format still checks it.)
HEAVY_TIDY_FILES='./test/integration/MockLayer1Layer0Test.cpp ./test/integration/Layer1ScaleTest.cpp ./test/integration/DhtNodeExternalApiTest.cpp ./test/integration/KademliaCorrectnessTest.cpp'
TIDY_FILES=$(echo "$FILES" | tr ' ' '\n' | grep -v 'test/integration/ConnectionLockingTest.cpp' | grep -v 'test/unit/PendingConnectionTest.cpp' | grep -v 'test/unit/SimulatorTest.cpp' | grep -v 'test/integration/SimultaneousConnectionsTest.cpp' | grep -v 'test/integration/ConnectionManagerIntegrationTest.cpp' | grep -v 'test/unit/DhtNodeRpcLocalTest.cpp' | grep -v 'test/integration/DhtNodeRpcRemoteTest.cpp' | grep -v 'test/unit/RoutingSessionTest.cpp' | grep -v 'test/unit/RecursiveOperationSessionTest.cpp' | grep -v 'test/unit/StoreRpcLocalTest.cpp' | grep -v 'test/unit/StoreManagerTest.cpp' | grep -v 'test/integration/MultipleEntryPointJoiningTest.cpp' | grep -v 'test/utils/DhtNodeTestUtils.hpp' | grep -v 'test/integration/DhtNodeTest.cpp' | grep -v 'test/integration/MockLayer1Layer0Test.cpp' | grep -v 'test/integration/Layer1ScaleTest.cpp' | grep -v 'test/integration/DhtNodeExternalApiTest.cpp' | grep -v 'test/integration/KademliaCorrectnessTest.cpp' | tr '\n' ' ')
# Chunked: one clangd process accumulates source-location space across the
# files it serves and never releases it; with the phase-A8 module graph a
# single process no longer survives the whole list (mid-batch the affected
# files degrade to non-module parses — spurious "unknown type name 'import'"
# — and clangd finally dies, aborting clangd-tidy with "Invalid header end").
# Verified: every 13-file chunk passes clean where the one-shot batch dies.
# The `< /dev/null` matters: a clangd-tidy spawned by xargs inherits the
# exhausted file-list pipe as stdin, which kills clangd at startup (verified
# both ways).
echo "$TIDY_FILES" | tr ' ' '\n' | grep -v '^$' | \
xargs -n 13 sh -c 'clangd-tidy -p "$0" "$@" < /dev/null' "$COMPILE_DB"
for heavy_file in $HEAVY_TIDY_FILES; do
echo "Running clangd-tidy (own process) on $heavy_file"
clangd-tidy -p "$COMPILE_DB" "$heavy_file" < /dev/null
done

echo "Running clang-format --dry-run on $FILES"
../../run-clang-format.py $FILES
Expand Down
22 changes: 15 additions & 7 deletions packages/streamr-dht/modules/connection/ConnectionManager.cppm
Original file line number Diff line number Diff line change
Expand Up @@ -573,13 +573,21 @@ public:
endpointsSnapshot = this->endpoints | std::views::values |
std::ranges::to<std::vector>();
}
return endpointsSnapshot | std::views::filter([](const auto& endpoint) {
return endpoint->isConnected();
}) |
std::views::transform([](const auto& endpoint) {
return endpoint->getPeerDescriptor();
}) |
std::ranges::to<std::vector>();
// Materialized with a single-pass loop, NOT a views::filter |
// ranges::to pipeline: for a forward range libc++'s to<vector> walks
// the range twice (ranges::distance to size the allocation, then the
// copy), and isConnected() is live state — an endpoint connecting
// between the two passes made the copy pass yield MORE elements than
// were counted, overflowing the allocation (heap-buffer-overflow
// caught by ASan in the 48-node layer1-scale test).
std::vector<PeerDescriptor> connections;
connections.reserve(endpointsSnapshot.size());
for (const auto& endpoint : endpointsSnapshot) {
if (endpoint->isConnected()) {
connections.push_back(endpoint->getPeerDescriptor());
}
}
return connections;
}

private:
Expand Down
Loading
Loading