diff options
author | Pieter Wuille <pieter@wuille.net> | 2023-07-26 13:19:31 -0400 |
---|---|---|
committer | Pieter Wuille <pieter@wuille.net> | 2023-08-23 19:56:24 -0400 |
commit | 27f9ba23efe82531a465c5e63bf7dc62b6a3a8db (patch) | |
tree | dabff76c69490b9d17486e7a255a14121c40438a /src/net.cpp | |
parent | 93594e42c3f92d82427d2b284ff0f94cdbebe99c (diff) |
net: add V1Transport lock protecting receive state
Rather than relying on the caller to prevent concurrent calls to the
various receive-side functions of Transport, introduce a private m_cs_recv
inside the implementation to protect the lock state.
Of course, this does not remove the need for callers to synchronize calls
entirely, as it is a stateful object, and e.g. the order in which Receive(),
Complete(), and GetMessage() are called matters. It seems impossible to use
a Transport object in a meaningful way in a multi-threaded way without some
form of external synchronization, but it still feels safer to make the
transport object itself responsible for protecting its internal state.
Diffstat (limited to 'src/net.cpp')
-rw-r--r-- | src/net.cpp | 7 |
1 files changed, 6 insertions, 1 deletions
diff --git a/src/net.cpp b/src/net.cpp index fa20136bb1..b350c58c61 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -719,6 +719,7 @@ bool CNode::ReceiveMsgBytes(Span<const uint8_t> msg_bytes, bool& complete) int V1Transport::readHeader(Span<const uint8_t> msg_bytes) { + AssertLockHeld(m_recv_mutex); // copy data to temporary parsing buffer unsigned int nRemaining = CMessageHeader::HEADER_SIZE - nHdrPos; unsigned int nCopy = std::min<unsigned int>(nRemaining, msg_bytes.size()); @@ -759,6 +760,7 @@ int V1Transport::readHeader(Span<const uint8_t> msg_bytes) int V1Transport::readData(Span<const uint8_t> msg_bytes) { + AssertLockHeld(m_recv_mutex); unsigned int nRemaining = hdr.nMessageSize - nDataPos; unsigned int nCopy = std::min<unsigned int>(nRemaining, msg_bytes.size()); @@ -776,7 +778,8 @@ int V1Transport::readData(Span<const uint8_t> msg_bytes) const uint256& V1Transport::GetMessageHash() const { - assert(Complete()); + AssertLockHeld(m_recv_mutex); + assert(CompleteInternal()); if (data_hash.IsNull()) hasher.Finalize(data_hash); return data_hash; @@ -784,9 +787,11 @@ const uint256& V1Transport::GetMessageHash() const CNetMessage V1Transport::GetMessage(const std::chrono::microseconds time, bool& reject_message) { + AssertLockNotHeld(m_recv_mutex); // Initialize out parameter reject_message = false; // decompose a single CNetMessage from the TransportDeserializer + LOCK(m_recv_mutex); CNetMessage msg(std::move(vRecv)); // store message type string, time, and sizes |