8000 gh-135371: Fix asyncio introspection output to include internal coroutine chains by pablogsal · Pull Request #135436 · python/cpython · GitHub
[go: up one dir, main page]

Skip to content

gh-135371: Fix asyncio introspection output to include internal coroutine chains #135436

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 8 commits into from
Jun 14, 2025
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Fix linting
  • Loading branch information
pablogsal committed Jun 12, 2025
commit 345219c774a21643f1ffc6c12bcff009d6313293
28 changes: 14 additions & 14 deletions Lib/asyncio/tools.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,14 +41,14 @@ def _index(result):
task_id = task_info.task_id
task_name = task_info.task_name
id2name[task_id] = task_name

# Store the internal coroutine stack for this task
if task_info.coroutine_stack:
for coro_info in task_info.coroutine_stack:
call_stack = coro_info.call_stack
internal_stack = [_format_stack_entry(frame) for frame in call_stack]
task_stacks[task_id] = internal_stack

# Add the awaited_by relationships (external dependencies)
if task_info.awaited_by:
for coro_info in task_info.awaited_by:
Expand All @@ -69,7 +69,7 @@ def get_or_create_cor_node(parent, frame):
"""Get existing coroutine node or create new one under parent"""
if frame in cor_nodes[parent]:
return cor_nodes[parent][frame]

node_key = (NodeType.COROUTINE, f"c{next(next_cor_id)}")
id2label[node_key] = frame
children[parent].append(node_key)
Expand All @@ -81,7 +81,7 @@ def get_or_create_cor_node(parent, frame):
cur = (NodeType.TASK, parent_id)
for frame in reversed(stack):
cur = get_or_create_cor_node(cur, frame)

child_key = (NodeType.TASK, child_id)
if child_key not in children[cur]:
children[cur].append(child_key)
Expand Down Expand Up @@ -179,39 +179,39 @@ def render(node, prefix="", last=True, buf=None):
def build_task_table(result):
id2name, _, _ = _index(result)
table = []

for awaited_info in result:
thread_id = awaited_info.thread_id
for task_info in awaited_info.awaited_by:
# Get task info
task_id = task_info.task_id
task_name = task_info.task_name

# Build coroutine stack string
frames = [frame for coro in task_info.coroutine_stack
frames = [frame for coro in task_info.coroutine_stack
for frame in coro.call_stack]
coro_stack = " -> ".join(_format_stack_entry(x).split(" ")[0]
coro_stack = " -> ".join(_format_stack_entry(x).split(" ")[0]
for x in frames)

# Handle tasks with no awaiters
if not task_info.awaited_by:
table.append([thread_id, hex(task_id), task_name, coro_stack,
"", "", "0x0"])
continue

# Handle tasks with awaiters
for coro_info in task_info.awaited_by:
parent_id = coro_info.task_name
awaiter_frames = [_format_stack_entry(x).split(" ")[0]
awaiter_frames = [_format_stack_entry(x).split(" ")[0]
for x in coro_info.call_stack]
awaiter_chain = " -> ".join(awaiter_frames)
awaiter_name = id2name.get(parent_id, "Unknown")
parent_id_str = (hex(parent_id) if isinstance(parent_id, int)
parent_id_str = (hex(parent_id) if isinstance(parent_id, int)
else str(parent_id))

table.append([thread_id, hex(task_id), task_name, coro_stack,
awaiter_chain, awaiter_name, parent_id_str])

return table

def _print_cycle_exception(exception: CycleFoundException):
Expand Down
1 change: 0 additions & 1 deletion Lib/test/test_external_inspection.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import asyncio
import unittest
import os
import textwrap
Expand All @@ -19,7 +18,7 @@
try:
from _remote_debugging import PROCESS_VM_READV_SUPPORTED
from _remote_debugging import RemoteUnwinder
from _remote_debugging import FrameInfo, CoroInfo, TaskInfo, AwaitedInfo

Check failure on line 21 in Lib/test/test_external_inspection.py

View workflow job for this annotation

GitHub Actions / lint

Ruff (F401)

Lib/test/test_external_inspection.py:21:66: F401 `_remote_debugging.AwaitedInfo` imported but unused; consider using `importlib.util.find_spec` to test for availability
except ImportError:
raise unittest.SkipTest(
"Test only runs when _remote_debugging is available"
Expand Down
Loading
0