From f39c1e6f4c2f7595a0d8b369f9edf6bb0132c6ce Mon Sep 17 00:00:00 2001 From: pasta Date: Tue, 19 Nov 2024 10:26:33 -0600 Subject: [PATCH] fix: guard m_can_tx_relay behind m_tx_relay_mutex; make it private; add additional annotations Originally introduced in pr 6365; this datarace was discovered using tsan locally, and running feature_llmq_chainlocks 5 times. 1 out of 5 times failed --- src/net_processing.cpp | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/src/net_processing.cpp b/src/net_processing.cpp index 8676ad3371..b6f75dfa00 100644 --- a/src/net_processing.cpp +++ b/src/net_processing.cpp @@ -309,21 +309,23 @@ struct Peer { /** * (Bitcoin) Initializes a TxRelay struct for this peer. Can be called at most once for a peer. * (Dash) Enables the flag that allows GetTxRelay() to return m_tx_relay */ - TxRelay* SetTxRelay() + TxRelay* SetTxRelay() LOCKS_EXCLUDED(m_tx_relay_mutex) { + LOCK(m_tx_relay_mutex); Assume(!m_can_tx_relay); m_can_tx_relay = true; - return WITH_LOCK(m_tx_relay_mutex, return m_tx_relay.get()); + return m_tx_relay.get(); }; - TxRelay* GetInvRelay() + TxRelay* GetInvRelay() LOCKS_EXCLUDED(m_tx_relay_mutex) { return WITH_LOCK(m_tx_relay_mutex, return m_tx_relay.get()); } - TxRelay* GetTxRelay() + TxRelay* GetTxRelay() LOCKS_EXCLUDED(m_tx_relay_mutex) { - return m_can_tx_relay ? WITH_LOCK(m_tx_relay_mutex, return m_tx_relay.get()) : nullptr; + LOCK(m_tx_relay_mutex); + return m_can_tx_relay ? m_tx_relay.get() : nullptr; }; /** A vector of addresses to send to the peer, limited to MAX_ADDR_TO_SEND. */ @@ -353,8 +355,6 @@ struct Peer { * This field must correlate with whether m_addr_known has been * initialized.*/ std::atomic_bool m_addr_relay_enabled{false}; - /** Whether a peer can relay transactions */ - bool m_can_tx_relay{false}; /** Whether a getaddr request to this peer is outstanding. */ bool m_getaddr_sent GUARDED_BY(NetEventsInterface::g_msgproc_mutex){false}; /** Guards address sending timers. */ @@ -406,6 +406,8 @@ private: * (non-transaction relay should use GetInvRelay(), which will provide * unconditional access) */ std::unique_ptr m_tx_relay GUARDED_BY(m_tx_relay_mutex){std::make_unique()}; + /** Whether a peer can relay transactions */ + bool m_can_tx_relay GUARDED_BY(m_tx_relay_mutex) {false}; }; using PeerRef = std::shared_ptr;