33import textwrap
44import importlib
55import sys
6- from test .support import os_helper , SHORT_TIMEOUT
6+ from test .support import os_helper , SHORT_TIMEOUT , busy_retry
77from test .support .script_helper import make_script
88
99import subprocess
@@ -361,7 +361,7 @@ def test_async_global_awaited_by(self):
361361 import random
362362 import sys
363363 from string import ascii_lowercase, digits
364- from test.support import socket_helper
364+ from test.support import socket_helper, SHORT_TIMEOUT
365365
366366 HOST = '127.0.0.1'
367367 PORT = socket_helper.find_unused_port()
@@ -386,7 +386,7 @@ async def echo_client(message):
386386 assert message == data.decode()
387387 writer.close()
388388 await writer.wait_closed()
389- await asyncio.sleep(10 )
389+ await asyncio.sleep(SHORT_TIMEOUT )
390390
391391 async def echo_client_spam(server):
392392 async with asyncio.TaskGroup() as tg:
@@ -426,16 +426,34 @@ async def main():
426426 with open (fifo , "r" ) as fifo_file :
427427 response = fifo_file .read ()
428428 self .assertEqual (response , "ready" )
429- all_awaited_by = get_all_awaited_by (p .pid )
429+ for _ in busy_retry (SHORT_TIMEOUT ):
430+ try :
431+ all_awaited_by = get_all_awaited_by (p .pid )
432+ except RuntimeError as re :
433+ # This call reads a linked list in another process with
434+ # no synchronization. That occasionally leads to invalid
435+ # reads. Here we avoid making the test flaky.
436+ msg = str (re )
437+ if msg .startswith ("Unknown error reading memory" ):
438+ continue
439+ elif msg .startswith ("Unhandled frame owner" ):
440+ continue
441+ raise # Unrecognized exception, safest not to ignore it
442+ else :
443+ break
430444 # expected: a list of two elements: 1 thread, 1 interp
431445 self .assertEqual (len (all_awaited_by ), 2 )
432446 # expected: a tuple with the thread ID and the awaited_by list
433447 self .assertEqual (len (all_awaited_by [0 ]), 2 )
434448 entries = all_awaited_by [0 ][1 ]
449+ # expected: at least 1000 pending tasks
435450 self .assertGreaterEqual (len (entries ), 1000 )
451+ # the first three tasks stem from the code structure
436452 self .assertIn (('Task-1' , []), entries )
437453 self .assertIn (('server task' , [[['main' ], 'Task-1' , []]]), entries )
438454 self .assertIn (('echo client spam' , [[['main' ], 'Task-1' , []]]), entries )
455+ # the final task will have some random number, but it should for
456+ # sure be one of the echo client spam horde
439457 self .assertEqual ([[['echo_client_spam' ], 'echo client spam' , [[['main' ], 'Task-1' , []]]]], entries [- 1 ][1 ])
440458 except PermissionError :
441459 self .skipTest (
0 commit comments