+ def test_thread_recv_while_main_thread_sends(self):
+ # GH-137583: Locking was added to calls to send() and recv() on SSL
+ # socket objects. This seemed fine at the surface level because those
+ # calls weren't re-entrant, but recv() calls would implicitly mimick
+ # holding a lock by blocking until it received data. This means that
+ # if a thread started to infinitely block until data was received, calls
+ # to send() would deadlock, because it would wait forever on the lock
+ # that the recv() call held.
+ data = b"1" * 1024
+ event = threading.Event()
+ def background(sock):
+ event.set()
+ received = sock.recv(len(data))
+ self.assertEqual(received, data)
+
+ client_context, server_context, hostname = testing_context()
+ server = ThreadedEchoServer(context=server_context)
+ with server:
+ with client_context.wrap_socket(socket.socket(),
+ server_hostname=hostname) as sock:
+ sock.connect((HOST, server.port))
+ sock.settimeout(1)
+ sock.setblocking(1)
+ # Ensure that the server is ready to accept requests
+ sock.sendall(b"123")
+ self.assertEqual(sock.recv(3), b"123")
+ with threading_helper.catch_threading_exception() as cm:
+ thread = threading.Thread(target=background,
+ args=(sock,), daemon=True)
+ thread.start()
+ event.wait()
+ sock.sendall(data)
+ thread.join()
+ if cm.exc_value is not None:
+ raise cm.exc_value
+