From cfe42ff0a7de05a0f9a1374bcecfc31e4f2835df Mon Sep 17 00:00:00 2001 From: Timofey Ivankov Date: Mon, 2 Nov 2026 15:35:42 +0300 Subject: [PATCH] gh-161173: Fix outdated docs for get_async_stack_trace --- Modules/_remote_debugging/clinic/module.c.h | 73 ++++++++++++++------ Modules/_remote_debugging/module.c | 76 ++++++++++++++------- 2 files changed, 102 insertions(+), 47 deletions(-) diff --git a/Modules/_remote_debugging/clinic/module.c.h b/Modules/_remote_debugging/clinic/module.c.h index 349113c36fb5f0..9895286cdb8019 100644 --- a/Modules/_remote_debugging/clinic/module.c.h +++ b/Modules/_remote_debugging/clinic/module.c.h @@ -362,16 +362,35 @@ PyDoc_STRVAR(_remote_debugging_RemoteUnwinder_get_async_stack_trace__doc__, "all tasks that transitively depend on it (tasks waiting for the\n" "running task, tasks waiting for those tasks, etc.).\n" "\n" -"Returns a list of per-thread results, where each thread result\n" -"contains:\n" -"- Thread ID\n" -"- List of task information for the running task and all its waiters\n" +"Returns:\n" +" A list of AwaitedInfo objects, where each object contains:\n" "\n" -"Each task info contains:\n" -"- Task ID (memory address)\n" -"- Task name\n" -"- Call stack frames: List of (func_name, filename, lineno)\n" -"- List of tasks waiting for this task (recursive structure)\n" +" - thread_id (int): Identifier of the thread.\n" +" - awaited_by (list[TaskInfo]): The running task and all its\n" +" transitive waiters.\n" +"\n" +"Each TaskInfo contains:\n" +" - task_id (int): Identifier of the task.\n" +" - task_name (str): Name of the task.\n" +" - coroutine_stack (list[CoroInfo]): Stack of coroutine frames.\n" +" - awaited_by (list[CoroInfo]): Coroutine information for\n" +" tasks or futures awaiting this task.\n" +"\n" +"Each CoroInfo contains:\n" +" - call_stack (list[FrameInfo]): Frames for the coroutine.\n" +" - task_name (int): Identifier of the task or future.\n" +"\n" +"Each FrameInfo contains:\n" +" - filename (str): Source code filename.\n" +" - location (LocationInfo | None): Source location, if available.\n" +" - funcname (str): Function name.\n" +" - opcode (int | None): Opcode, if available.\n" +"\n" +"Each LocationInfo contains:\n" +" - lineno (int): Starting line number.\n" +" - end_lineno (int): Ending line number.\n" +" - col_offset (int): Starting column offset.\n" +" - end_col_offset (int): Ending column offset.\n" "\n" "Raises:\n" " RuntimeError: If AsyncioDebug section is not available in the\n" @@ -379,18 +398,28 @@ PyDoc_STRVAR(_remote_debugging_RemoteUnwinder_get_async_stack_trace__doc__, " MemoryError: If memory allocation fails\n" " OSError: If reading from the remote process fails\n" "\n" -"Example output (similar structure to get_all_awaited_by but only for\n" -"running tasks):\n" -"[\n" -" (140234, [\n" -" (4345585712, \'main_task\',\n" -" [(\"run_server\", \"server.py\", 127), (\"main\", \"app.py\", 23)],\n" -" [\n" -" (4345585800, \'worker_1\', [...], [...]),\n" -" (4345585900, \'worker_2\', [...], [...])\n" -" ])\n" -" ])\n" -"]"); +"Example output:\n" +"\n" +" [\n" +" AwaitedInfo(thread_id=140234, awaited_by=[\n" +" TaskInfo(\n" +" task_id=1,\n" +" task_name=\"worker\",\n" +" coroutine_stack=[\n" +" CoroInfo(call_stack=[...], task_name=1)\n" +" ],\n" +" awaited_by=[CoroInfo(call_stack=[...], task_name=2)]\n" +" ),\n" +" TaskInfo(\n" +" task_id=2,\n" +" task_name=\"main\",\n" +" coroutine_stack=[\n" +" CoroInfo(call_stack=[...], task_name=2)\n" +" ],\n" +" awaited_by=[]\n" +" )\n" +" ])\n" +" ]"); #define _REMOTE_DEBUGGING_REMOTEUNWINDER_GET_ASYNC_STACK_TRACE_METHODDEF \ {"get_async_stack_trace", (PyCFunction)_remote_debugging_RemoteUnwinder_get_async_stack_trace, METH_NOARGS, _remote_debugging_RemoteUnwinder_get_async_stack_trace__doc__}, @@ -1711,4 +1740,4 @@ _remote_debugging_get_gc_stats(PyObject *module, PyObject *const *args, Py_ssize exit: return return_value; } -/*[clinic end generated code: output=8424a993a85ef2bd input=a9049054013a1b77]*/ +/*[clinic end generated code: output=2667550106e045bd input=a9049054013a1b77]*/ diff --git a/Modules/_remote_debugging/module.c b/Modules/_remote_debugging/module.c index efb6d600247bf7..28f73a86dcdbda 100644 --- a/Modules/_remote_debugging/module.c +++ b/Modules/_remote_debugging/module.c @@ -1010,16 +1010,35 @@ For each thread with a running task, returns the running task plus all tasks that transitively depend on it (tasks waiting for the running task, tasks waiting for those tasks, etc.). -Returns a list of per-thread results, where each thread result -contains: -- Thread ID -- List of task information for the running task and all its waiters +Returns: + A list of AwaitedInfo objects, where each object contains: -Each task info contains: -- Task ID (memory address) -- Task name -- Call stack frames: List of (func_name, filename, lineno) -- List of tasks waiting for this task (recursive structure) + - thread_id (int): Identifier of the thread. + - awaited_by (list[TaskInfo]): The running task and all its + transitive waiters. + +Each TaskInfo contains: + - task_id (int): Identifier of the task. + - task_name (str): Name of the task. + - coroutine_stack (list[CoroInfo]): Stack of coroutine frames. + - awaited_by (list[CoroInfo]): Coroutine information for + tasks or futures awaiting this task. + +Each CoroInfo contains: + - call_stack (list[FrameInfo]): Frames for the coroutine. + - task_name (int): Identifier of the task or future. + +Each FrameInfo contains: + - filename (str): Source code filename. + - location (LocationInfo | None): Source location, if available. + - funcname (str): Function name. + - opcode (int | None): Opcode, if available. + +Each LocationInfo contains: + - lineno (int): Starting line number. + - end_lineno (int): Ending line number. + - col_offset (int): Starting column offset. + - end_col_offset (int): Ending column offset. Raises: RuntimeError: If AsyncioDebug section is not available in the @@ -1027,27 +1046,34 @@ Each task info contains: MemoryError: If memory allocation fails OSError: If reading from the remote process fails -Example output (similar structure to get_all_awaited_by but only for -running tasks): -[ - # Thread 140234 results - (140234, [ - # Running task and its complete waiter dependency graph - (4345585712, 'main_task', - [("run_server", "server.py", 127), ("main", "app.py", 23)], - [ - # Tasks waiting for main_task - (4345585800, 'worker_1', [...], [...]), - (4345585900, 'worker_2', [...], [...]) - ]) - ]) -] +Example output: + + [ + AwaitedInfo(thread_id=140234, awaited_by=[ + TaskInfo( + task_id=1, + task_name="worker", + coroutine_stack=[ + CoroInfo(call_stack=[...], task_name=1) + ], + awaited_by=[CoroInfo(call_stack=[...], task_name=2)] + ), + TaskInfo( + task_id=2, + task_name="main", + coroutine_stack=[ + CoroInfo(call_stack=[...], task_name=2) + ], + awaited_by=[] + ) + ]) + ] [clinic start generated code]*/ static PyObject * _remote_debugging_RemoteUnwinder_get_async_stack_trace_impl(RemoteUnwinderObject *self) -/*[clinic end generated code: output=6433d52b55e87bbe input=bc802e4221c99399]*/ +/*[clinic end generated code: output=6433d52b55e87bbe input=0532031a7c495491]*/ { if (ensure_async_debug_offsets(self) < 0) { return NULL;