From bb7bffed799dc5ad8b606768164fce46d4cbf9d0 Mon Sep 17 00:00:00 2001 From: stratospher <44024636+stratospher@users.noreply.github.com> Date: Fri, 24 Nov 2023 23:55:44 +0530 Subject: [PATCH] [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 Co-authored-by: theStack --- test/functional/test_framework/p2p.py | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/test/functional/test_framework/p2p.py b/test/functional/test_framework/p2p.py index 27f921702cf..dcb93e9acce 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: