Skip to content

Commit dc610b7

Browse files
committed
gh-149230: Test async tasks in non-main threads
1 parent 7cff9cb commit dc610b7

1 file changed

Lines changed: 74 additions & 0 deletions

File tree

Lib/test/test_external_inspection.py

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1368,6 +1368,80 @@ def matches_awaited_by_pattern(task):
13681368
finally:
13691369
_cleanup_sockets(client_socket, server_socket)
13701370

1371+
@skip_if_not_supported
1372+
@unittest.skipIf(
1373+
sys.platform == "linux" and not PROCESS_VM_READV_SUPPORTED,
1374+
"Test only runs on Linux with process_vm_readv support",
1375+
)
1376+
def test_async_global_awaited_by_from_non_main_thread(self):
1377+
port = find_unused_port()
1378+
script = textwrap.dedent(
1379+
f"""\
1380+
import asyncio
1381+
import socket
1382+
import threading
1383+
import time
1384+
1385+
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
1386+
sock.connect(('localhost', {port}))
1387+
1388+
async def worker_main():
1389+
task = asyncio.create_task(
1390+
asyncio.sleep(10_000),
1391+
name="worker task",
1392+
)
1393+
await asyncio.sleep(0)
1394+
sock.sendall(f"ready:{{threading.get_native_id()}}\\n".encode())
1395+
await task
1396+
1397+
def run_worker_loop():
1398+
asyncio.run(worker_main())
1399+
1400+
threading.Thread(
1401+
target=run_worker_loop,
1402+
name="async-worker",
1403+
daemon=True,
1404+
).start()
1405+
time.sleep(10_000)
1406+
"""
1407+
)
1408+
1409+
with os_helper.temp_dir() as work_dir:
1410+
script_dir = os.path.join(work_dir, "script_pkg")
1411+
os.mkdir(script_dir)
1412+
1413+
server_socket = _create_server_socket(port)
1414+
script_name = _make_test_script(script_dir, "script", script)
1415+
client_socket = None
1416+
1417+
try:
1418+
with _managed_subprocess([sys.executable, script_name]) as p:
1419+
client_socket, _ = server_socket.accept()
1420+
server_socket.close()
1421+
server_socket = None
1422+
1423+
response = _wait_for_signal(client_socket, b"ready:")
1424+
worker_thread_id = int(
1425+
response.split(b"ready:", 1)[1].splitlines()[0]
1426+
)
1427+
1428+
for _ in busy_retry(SHORT_TIMEOUT):
1429+
all_awaited_by = get_all_awaited_by(p.pid)
1430+
if any(
1431+
task.task_name == "worker task"
1432+
for info in all_awaited_by
1433+
if info.thread_id == worker_thread_id
1434+
for task in info.awaited_by
1435+
):
1436+
break
1437+
else:
1438+
self.fail(
1439+
"get_all_awaited_by() did not report "
1440+
"the asyncio task from the non-main thread"
1441+
)
1442+
finally:
1443+
_cleanup_sockets(client_socket, server_socket)
1444+
13711445
@skip_if_not_supported
13721446
@unittest.skipIf(
13731447
sys.platform == "linux" and not PROCESS_VM_READV_SUPPORTED,

0 commit comments

Comments
 (0)