From fa2afba28b5776a710386a3bacd5cb308149d671 Mon Sep 17 00:00:00 2001 From: MarcoFalke <*~=`'#}+{/-|&$^_@721217.xyz> Date: Fri, 15 May 2026 11:15:36 +0200 Subject: [PATCH 1/4] p2p: Release m_peer_mutex early in InitiateTxBroadcastToAll --- src/net_processing.cpp | 21 ++++++++++++++++++--- test/sanitizer_suppressions/tsan | 5 ----- 2 files changed, 18 insertions(+), 8 deletions(-) diff --git a/src/net_processing.cpp b/src/net_processing.cpp index 631e968da7f0..c4be0e61b585 100644 --- a/src/net_processing.cpp +++ b/src/net_processing.cpp @@ -575,6 +575,9 @@ class PeerManagerImpl final : public PeerManager * May return an empty shared_ptr if the Peer object can't be found. */ PeerRef RemovePeer(NodeId id) EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex); + /// Get all existing peers in m_peer_map. + std::vector GetAllPeers() const EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex); + /** Mark a peer as misbehaving, which will cause it to be disconnected and its * address discouraged. */ void Misbehaving(Peer& peer, const std::string& message); @@ -1785,6 +1788,17 @@ PeerRef PeerManagerImpl::RemovePeer(NodeId id) return ret; } +std::vector PeerManagerImpl::GetAllPeers() const +{ + std::vector peers; + LOCK(m_peer_mutex); + peers.reserve(m_peer_map.size()); + for (const auto& [_, peer] : m_peer_map) { + peers.push_back(peer); + } + return peers; +} + bool PeerManagerImpl::GetNodeStateStats(NodeId nodeid, CNodeStateStats& stats) const { { @@ -2243,9 +2257,10 @@ void PeerManagerImpl::SendPings() void PeerManagerImpl::InitiateTxBroadcastToAll(const Txid& txid, const Wtxid& wtxid) { - LOCK(m_peer_mutex); - for(auto& it : m_peer_map) { - Peer& peer = *it.second; + for (const PeerRef& peer_ref : GetAllPeers()) { + if (!peer_ref) continue; + Peer& peer{*peer_ref}; + auto tx_relay = peer.GetTxRelay(); if (!tx_relay) continue; diff --git a/test/sanitizer_suppressions/tsan b/test/sanitizer_suppressions/tsan index 661571018b36..34004c6768ba 100644 --- a/test/sanitizer_suppressions/tsan +++ b/test/sanitizer_suppressions/tsan @@ -3,11 +3,6 @@ # # https://github.com/google/sanitizers/wiki/ThreadSanitizerSuppressions -# deadlock (TODO fix) -# To reproduce, see: -# https://github.com/bitcoin/bitcoin/issues/19303#issuecomment-1514926359 -deadlock:Chainstate::ConnectTip - # Intentional deadlock in tests deadlock:sync_tests::potential_deadlock_detected From fba713a28c89ee565cc2d20bdd3b0690e3a1f5b8 Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Mon, 8 Jun 2026 19:06:33 +0100 Subject: [PATCH 2/4] scripted-diff: Rename UNIQUE_NAME to BITCOIN_UNIQUE_NAME The `nb30.h` Windows header defines `UNIQUE_NAME` as a macro. This introduces a fragile dependency on header inclusion order: if Windows headers happen to be included before `UNIQUE_NAME` is used, the preprocessor expands it into a numeric literal, causing syntax errors. Rename the macro to `BITCOIN_UNIQUE_NAME` to remove this fragility and avoid the collision entirely. -BEGIN VERIFY SCRIPT- sed -i 's/\/BITCOIN_UNIQUE_NAME/g' $(git grep -l 'UNIQUE_NAME' ./src/) -END VERIFY SCRIPT- --- src/logging/timer.h | 8 ++++---- src/sync.h | 4 ++-- src/test/util/logging.h | 2 +- src/util/macros.h | 2 +- src/util/stdmutex.h | 2 +- 5 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/logging/timer.h b/src/logging/timer.h index 2b183822e969..1706c9e71bb3 100644 --- a/src/logging/timer.h +++ b/src/logging/timer.h @@ -99,13 +99,13 @@ class Timer #define LOG_TIME_MICROS_WITH_CATEGORY(end_msg, log_category) \ - BCLog::Timer UNIQUE_NAME(logging_timer)(__func__, end_msg, log_category) + BCLog::Timer BITCOIN_UNIQUE_NAME(logging_timer)(__func__, end_msg, log_category) #define LOG_TIME_MILLIS_WITH_CATEGORY(end_msg, log_category) \ - BCLog::Timer UNIQUE_NAME(logging_timer)(__func__, end_msg, log_category) + BCLog::Timer BITCOIN_UNIQUE_NAME(logging_timer)(__func__, end_msg, log_category) #define LOG_TIME_MILLIS_WITH_CATEGORY_MSG_ONCE(end_msg, log_category) \ - BCLog::Timer UNIQUE_NAME(logging_timer)(__func__, end_msg, log_category, /* msg_on_completion=*/false) + BCLog::Timer BITCOIN_UNIQUE_NAME(logging_timer)(__func__, end_msg, log_category, /* msg_on_completion=*/false) #define LOG_TIME_SECONDS(end_msg) \ - BCLog::Timer UNIQUE_NAME(logging_timer)(__func__, end_msg) + BCLog::Timer BITCOIN_UNIQUE_NAME(logging_timer)(__func__, end_msg) #endif // BITCOIN_LOGGING_TIMER_H diff --git a/src/sync.h b/src/sync.h index 123184d44f61..28bc78e91157 100644 --- a/src/sync.h +++ b/src/sync.h @@ -251,7 +251,7 @@ class SCOPED_LOCKABLE UniqueLock : public MutexType::unique_lock // it is not possible to use the lock's copy of the mutex for that purpose. // Instead, the original mutex needs to be passed back to the reverse_lock for // the sake of thread-safety analysis, but it is not actually used otherwise. -#define REVERSE_LOCK(g, cs) typename std::decay::type::reverse_lock UNIQUE_NAME(revlock)(g, cs, #cs, __FILE__, __LINE__) +#define REVERSE_LOCK(g, cs) typename std::decay::type::reverse_lock BITCOIN_UNIQUE_NAME(revlock)(g, cs, #cs, __FILE__, __LINE__) // When locking a Mutex, require negative capability to ensure the lock // is not already held @@ -265,7 +265,7 @@ inline MutexType& MaybeCheckNotHeld(MutexType& m) LOCKS_EXCLUDED(m) LOCK_RETURNE template inline MutexType* MaybeCheckNotHeld(MutexType* m) LOCKS_EXCLUDED(m) LOCK_RETURNED(m) { return m; } -#define LOCK(cs) UniqueLock UNIQUE_NAME(criticalblock)(MaybeCheckNotHeld(cs), #cs, __FILE__, __LINE__) +#define LOCK(cs) UniqueLock BITCOIN_UNIQUE_NAME(criticalblock)(MaybeCheckNotHeld(cs), #cs, __FILE__, __LINE__) #define LOCK2(cs1, cs2) \ UniqueLock criticalblock1(MaybeCheckNotHeld(cs1), #cs1, __FILE__, __LINE__); \ UniqueLock criticalblock2(MaybeCheckNotHeld(cs2), #cs2, __FILE__, __LINE__) diff --git a/src/test/util/logging.h b/src/test/util/logging.h index ed3ee19e1bbf..6df208d841d5 100644 --- a/src/test/util/logging.h +++ b/src/test/util/logging.h @@ -39,6 +39,6 @@ class DebugLogHelper MatchFn m_match; }; -#define ASSERT_DEBUG_LOG(message) DebugLogHelper UNIQUE_NAME(debugloghelper)(message) +#define ASSERT_DEBUG_LOG(message) DebugLogHelper BITCOIN_UNIQUE_NAME(debugloghelper)(message) #endif // BITCOIN_TEST_UTIL_LOGGING_H diff --git a/src/util/macros.h b/src/util/macros.h index 9ad2fa6ef46b..eedd23c69265 100644 --- a/src/util/macros.h +++ b/src/util/macros.h @@ -8,7 +8,7 @@ #define PASTE(x, y) x ## y #define PASTE2(x, y) PASTE(x, y) -#define UNIQUE_NAME(name) PASTE2(name, __COUNTER__) +#define BITCOIN_UNIQUE_NAME(name) PASTE2(name, __COUNTER__) /** * Converts the parameter X to a string after macro replacement on X has been performed. diff --git a/src/util/stdmutex.h b/src/util/stdmutex.h index ab89a987685c..d2ac1ba195e3 100644 --- a/src/util/stdmutex.h +++ b/src/util/stdmutex.h @@ -38,6 +38,6 @@ class LOCKABLE StdMutex : public std::mutex }; // Provide STDLOCK(..) wrapper around StdMutex::Guard that checks the lock is not already held -#define STDLOCK(cs) StdMutex::Guard UNIQUE_NAME(criticalblock){StdMutex::CheckNotHeld(cs)} +#define STDLOCK(cs) StdMutex::Guard BITCOIN_UNIQUE_NAME(criticalblock){StdMutex::CheckNotHeld(cs)} #endif // BITCOIN_UTIL_STDMUTEX_H From 6d47f7cc6fc6802fc620bfe578d8f6a765be1fc0 Mon Sep 17 00:00:00 2001 From: fanquake Date: Wed, 3 Jun 2026 10:55:34 +0100 Subject: [PATCH 3/4] ci: use llvm 22.1.7 --- ci/test/01_base_install.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ci/test/01_base_install.sh b/ci/test/01_base_install.sh index 512d1a32e87c..7f6554eaaadc 100755 --- a/ci/test/01_base_install.sh +++ b/ci/test/01_base_install.sh @@ -62,7 +62,7 @@ if [ -n "$PIP_PACKAGES" ]; then fi if [[ -n "${USE_INSTRUMENTED_LIBCPP}" ]]; then - ${CI_RETRY_EXE} git clone --depth=1 https://github.com/llvm/llvm-project -b "llvmorg-22.1.3" /llvm-project + ${CI_RETRY_EXE} git clone --depth=1 https://github.com/llvm/llvm-project -b "llvmorg-22.1.7" /llvm-project cmake -G Ninja -B /cxx_build/ \ -DLLVM_ENABLE_RUNTIMES="libcxx;libcxxabi;libunwind" \ From 087f02c929cc1c09300822b02981acc710f1ab40 Mon Sep 17 00:00:00 2001 From: fanquake Date: Wed, 3 Jun 2026 10:56:17 +0100 Subject: [PATCH 4/4] ci: skip libunwind runtime in LLVM build Document why we use LIBCXXABI_USE_LLVM_UNWINDER=OFF. --- ci/test/01_base_install.sh | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/ci/test/01_base_install.sh b/ci/test/01_base_install.sh index 7f6554eaaadc..8b10ba10baac 100755 --- a/ci/test/01_base_install.sh +++ b/ci/test/01_base_install.sh @@ -64,8 +64,11 @@ fi if [[ -n "${USE_INSTRUMENTED_LIBCPP}" ]]; then ${CI_RETRY_EXE} git clone --depth=1 https://github.com/llvm/llvm-project -b "llvmorg-22.1.7" /llvm-project +# LLVM is configured with LIBCXXABI_USE_LLVM_UNWINDER=OFF, +# because libunwind doesn't handle exceptions under MSAN. +# https://github.com/llvm/llvm-project/issues/84348 cmake -G Ninja -B /cxx_build/ \ - -DLLVM_ENABLE_RUNTIMES="libcxx;libcxxabi;libunwind" \ + -DLLVM_ENABLE_RUNTIMES="libcxx;libcxxabi" \ -DCMAKE_BUILD_TYPE=Release \ -DLLVM_USE_SANITIZER="${USE_INSTRUMENTED_LIBCPP}" \ -DCMAKE_C_COMPILER=clang \