From a3ba8dd817e3ca97aed44386bf566faaa5d2d17a Mon Sep 17 00:00:00 2001 From: Pablo Galindo Date: Sun, 4 May 2025 10:11:35 +0200 Subject: [PATCH 1/3] gh-133141: Fix race in test_async_global_awaited_by Signed-off-by: Pablo Galindo --- Lib/test/test_external_inspection.py | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/Lib/test/test_external_inspection.py b/Lib/test/test_external_inspection.py index 4e82f567e1f429..bac583a8295e28 100644 --- a/Lib/test/test_external_inspection.py +++ b/Lib/test/test_external_inspection.py @@ -5,7 +5,7 @@ import sys import socket from unittest.mock import ANY -from test.support import os_helper, SHORT_TIMEOUT, busy_retry, requires_gil_enabled +from test.support import os_helper, SHORT_TIMEOUT, busy_retry from test.support.script_helper import make_script from test.support.socket_helper import find_unused_port @@ -406,7 +406,6 @@ async def main(): self.assertEqual(stack_trace, expected_stack_trace) @skip_if_not_supported - @requires_gil_enabled("gh-133359: occasionally flaky on AMD64") @unittest.skipIf(sys.platform == "linux" and not PROCESS_VM_READV_SUPPORTED, "Test only runs on Linux with process_vm_readv support") def test_async_global_awaited_by(self): @@ -447,6 +446,8 @@ async def echo_client(message): assert message == data.decode() writer.close() await writer.wait_closed() + # Signal we are ready to sleep + sock.sendall(b"ready") await asyncio.sleep(SHORT_TIMEOUT) async def echo_client_spam(server): @@ -456,8 +457,10 @@ async def echo_client_spam(server): random.shuffle(msg) tg.create_task(echo_client("".join(msg))) await asyncio.sleep(0) - # at least a 1000 tasks created - sock.sendall(b"ready") + # at least a 1000 tasks created. Each task will signal + # when is ready to avoid the race caused by the fact that + # tasks are waited on tg.__exit__ and we cannot signal when + # that happens otherwise # at this point all client tasks completed without assertion errors # let's wrap up the test server.close() @@ -489,8 +492,10 @@ async def main(): p = subprocess.Popen([sys.executable, script_name]) client_socket, _ = server_socket.accept() server_socket.close() - response = client_socket.recv(1024) - self.assertEqual(response, b"ready") + for _ in range(1000): + expected_response = b"ready" + response = client_socket.recv(len(expected_response)) + self.assertEqual(response, expected_response) for _ in busy_retry(SHORT_TIMEOUT): try: all_awaited_by = get_all_awaited_by(p.pid) @@ -527,12 +532,7 @@ async def main(): expected_stack = [[['_aexit', '__aexit__', 'echo_client_spam'], ANY]] tasks_with_stack = [task for task in entries if task[2] == expected_stack] self.assertGreaterEqual(len(tasks_with_stack), 1000) - - # the final task will have some random number, but it should for - # sure be one of the echo client spam horde (In windows this is not true - # for some reason) - if sys.platform != "win32": - self.assertEqual([[['_aexit', '__aexit__', 'echo_client_spam'], ANY]], entries[-1][2]) + self.assertEqual([[['_aexit', '__aexit__', 'echo_client_spam'], ANY]], entries[-1][2]) except PermissionError: self.skipTest( "Insufficient permissions to read the stack trace") From 7190e867cfc4e177da8a0ecfd764324045d53c80 Mon Sep 17 00:00:00 2001 From: Pablo Galindo Salgado Date: Sun, 4 May 2025 17:27:06 +0100 Subject: [PATCH 2/3] Update Lib/test/test_external_inspection.py --- Lib/test/test_external_inspection.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/Lib/test/test_external_inspection.py b/Lib/test/test_external_inspection.py index bac583a8295e28..eeb1d28e70b370 100644 --- a/Lib/test/test_external_inspection.py +++ b/Lib/test/test_external_inspection.py @@ -532,7 +532,12 @@ async def main(): expected_stack = [[['_aexit', '__aexit__', 'echo_client_spam'], ANY]] tasks_with_stack = [task for task in entries if task[2] == expected_stack] self.assertGreaterEqual(len(tasks_with_stack), 1000) - self.assertEqual([[['_aexit', '__aexit__', 'echo_client_spam'], ANY]], entries[-1][2]) + + # the final task will have some random number, but it should for + # sure be one of the echo client spam horde (In windows this is not true + # for some reason) + if sys.platform != "win32": + self.assertEqual([[['_aexit', '__aexit__', 'echo_client_spam'], ANY]], entries[-1][2])``` except PermissionError: self.skipTest( "Insufficient permissions to read the stack trace") From 8e0b7dce9a1f96e21a9796535b4dd0c0626734d1 Mon Sep 17 00:00:00 2001 From: Pablo Galindo Salgado Date: Sun, 4 May 2025 17:27:32 +0100 Subject: [PATCH 3/3] Update Lib/test/test_external_inspection.py --- Lib/test/test_external_inspection.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Lib/test/test_external_inspection.py b/Lib/test/test_external_inspection.py index eeb1d28e70b370..0fd704e698b90e 100644 --- a/Lib/test/test_external_inspection.py +++ b/Lib/test/test_external_inspection.py @@ -534,10 +534,10 @@ async def main(): self.assertGreaterEqual(len(tasks_with_stack), 1000) # the final task will have some random number, but it should for - # sure be one of the echo client spam horde (In windows this is not true - # for some reason) - if sys.platform != "win32": - self.assertEqual([[['_aexit', '__aexit__', 'echo_client_spam'], ANY]], entries[-1][2])``` + # sure be one of the echo client spam horde (In windows this is not true + # for some reason) + if sys.platform != "win32": + self.assertEqual([[['_aexit', '__aexit__', 'echo_client_spam'], ANY]], entries[-1][2]) except PermissionError: self.skipTest( "Insufficient permissions to read the stack trace")