aboutsummaryrefslogtreecommitdiff
path: root/test/functional/test_framework
diff options
context:
space:
mode:
authorstratospher <44024636+stratospher@users.noreply.github.com>2023-11-24 23:55:44 +0530
committerstratospher <44024636+stratospher@users.noreply.github.com>2024-01-25 11:09:52 +0530
commitbb7bffed799dc5ad8b606768164fce46d4cbf9d0 (patch)
tree8d54fc60710c543049c2c6877916f89b2a2743ef /test/functional/test_framework
parent5b91fb14aba7d7fe45c9ac364526815bec742356 (diff)
downloadbitcoin-bb7bffed799dc5ad8b606768164fce46d4cbf9d0.tar.xz
[test] Use lock for sending P2P messages in test framework
Messages are built, encrypted and sent over the socket in v2 connections. If a race condition happens between python's main thread and p2p thread with both of them trying to send a message, it's possible that the messages get encrypted with wrong keystream. Messages are built and sent over the socket in v1 connections. So there's no problem if messages are sent in the wrong order. Co-authored-by: Martin Zumsande <mzumsande@gmail.com> Co-authored-by: theStack <sebastian.falbesoner@gmail.com>
Diffstat (limited to 'test/functional/test_framework')
-rwxr-xr-xtest/functional/test_framework/p2p.py10
1 files changed, 7 insertions, 3 deletions
diff --git a/test/functional/test_framework/p2p.py b/test/functional/test_framework/p2p.py
index 27f921702c..dcb93e9acc 100755
--- a/test/functional/test_framework/p2p.py
+++ b/test/functional/test_framework/p2p.py
@@ -163,6 +163,9 @@ class P2PConnection(asyncio.Protocol):
# The underlying transport of the connection.
# Should only call methods on this from the NetworkThread, c.f. call_soon_threadsafe
self._transport = None
+ # This lock is acquired before sending messages over the socket. There's an implied lock order and
+ # p2p_lock must not be acquired after _send_lock as it could result in deadlocks.
+ self._send_lock = threading.Lock()
self.v2_state = None # EncryptedP2PState object needed for v2 p2p connections
@property
@@ -360,9 +363,10 @@ class P2PConnection(asyncio.Protocol):
This method takes a P2P payload, builds the P2P header and adds
the message to the send buffer to be sent over the socket."""
- tmsg = self.build_message(message)
- self._log_message("send", message)
- return self.send_raw_message(tmsg)
+ with self._send_lock:
+ tmsg = self.build_message(message)
+ self._log_message("send", message)
+ return self.send_raw_message(tmsg)
def send_raw_message(self, raw_message_bytes):
if not self.is_connected: