gh-150285: Fix too long docstrings in the _remote_debugging module (GH-150289)

This commit is contained in:
Serhiy Storchaka 2026-05-24 15:02:43 +03:00 committed by GitHub
parent 6bed57a3b6
commit cdc499ae77
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 249 additions and 179 deletions

View file

@ -21,33 +21,37 @@ PyDoc_STRVAR(_remote_debugging_RemoteUnwinder___init____doc__,
"\n"
"Args:\n"
" pid: Process ID of the target Python process to debug\n"
" all_threads: If True, initialize state for all threads in the process.\n"
" If False, only initialize for the main thread.\n"
" all_threads: If True, initialize state for all threads in the\n"
" process. If False, only initialize for the main thread.\n"
" only_active_thread: If True, only sample the thread holding the GIL.\n"
" mode: Profiling mode: 0=WALL (wall-time), 1=CPU (cpu-time), 2=GIL (gil-time).\n"
" Cannot be used together with all_threads=True.\n"
" debug: If True, chain exceptions to explain the sequence of events that\n"
" lead to the exception.\n"
" skip_non_matching_threads: If True, skip threads that don\'t match the selected mode.\n"
" If False, include all threads regardless of mode.\n"
" native: If True, include artificial \"<native>\" frames to denote calls to\n"
" non-Python code.\n"
" gc: If True, include artificial \"<GC>\" frames to denote active garbage\n"
" collection.\n"
" opcodes: If True, gather bytecode opcode information for instruction-level\n"
" profiling.\n"
" cache_frames: If True, enable frame caching optimization to avoid re-reading\n"
" unchanged parent frames between samples.\n"
" stats: If True, collect statistics about cache hits, memory reads, etc.\n"
" Use get_stats() to retrieve the collected statistics.\n"
" mode: Profiling mode: 0=WALL (wall-time), 1=CPU (cpu-time), 2=GIL\n"
" (gil-time). Cannot be used together with all_threads=True.\n"
" debug: If True, chain exceptions to explain the sequence of events\n"
" that lead to the exception.\n"
" skip_non_matching_threads: If True, skip threads that don\'t match\n"
" the selected mode. If False, include all threads regardless of\n"
" mode.\n"
" native: If True, include artificial \"<native>\" frames to denote\n"
" calls to non-Python code.\n"
" gc: If True, include artificial \"<GC>\" frames to denote active\n"
" garbage collection.\n"
" opcodes: If True, gather bytecode opcode information for\n"
" instruction-level profiling.\n"
" cache_frames: If True, enable frame caching optimization to avoid\n"
" re-reading unchanged parent frames between samples.\n"
" stats: If True, collect statistics about cache hits, memory reads,\n"
" etc. Use get_stats() to retrieve the collected statistics.\n"
"\n"
"The RemoteUnwinder provides functionality to inspect and debug a running Python\n"
"process, including examining thread states, stack frames and other runtime data.\n"
"The RemoteUnwinder provides functionality to inspect and debug a running\n"
"Python process, including examining thread states, stack frames and\n"
"other runtime data.\n"
"\n"
"Raises:\n"
" PermissionError: If access to the target process is denied\n"
" OSError: If unable to attach to the target process or access its memory\n"
" RuntimeError: If unable to read debug information from the target process\n"
" OSError: If unable to attach to the target process or access its\n"
" memory\n"
" RuntimeError: If unable to read debug information from the target\n"
" process\n"
" ValueError: If both all_threads and only_active_thread are True");
static int
@ -217,16 +221,21 @@ PyDoc_STRVAR(_remote_debugging_RemoteUnwinder_get_stack_trace__doc__,
"\n"
"Returns stack traces for all interpreters and threads in process.\n"
"\n"
"Each element in the returned list is a tuple of (interpreter_id, thread_list), where:\n"
"Each element in the returned list is a tuple of (interpreter_id,\n"
"thread_list), where:\n"
"- interpreter_id is the interpreter identifier\n"
"- thread_list is a list of tuples (thread_id, frame_list) for threads in that interpreter\n"
"- thread_list is a list of tuples (thread_id, frame_list) for\n"
" threads in that interpreter\n"
" - thread_id is the OS thread identifier\n"
" - frame_list is a list of tuples (function_name, filename, line_number) representing\n"
" the Python stack frames for that thread, ordered from most recent to oldest\n"
" - frame_list is a list of tuples (function_name, filename,\n"
" line_number) representing the Python stack frames for that\n"
" thread, ordered from most recent to oldest\n"
"\n"
"The threads returned depend on the initialization parameters:\n"
"- If only_active_thread was True: returns only the thread holding the GIL across all interpreters\n"
"- If all_threads was True: returns all threads across all interpreters\n"
"- If only_active_thread was True: returns only the thread holding\n"
" the GIL across all interpreters\n"
"- If all_threads was True: returns all threads across all\n"
" interpreters\n"
"- Otherwise: returns only the main thread of each interpreter\n"
"\n"
"Example:\n"
@ -250,10 +259,12 @@ PyDoc_STRVAR(_remote_debugging_RemoteUnwinder_get_stack_trace__doc__,
" ]\n"
"\n"
"Raises:\n"
" RuntimeError: If there is an error copying memory from the target process\n"
" RuntimeError: If there is an error copying memory from the\n"
" target process\n"
" OSError: If there is an error accessing the target process\n"
" PermissionError: If access to the target process is denied\n"
" UnicodeDecodeError: If there is an error decoding strings from the target process");
" UnicodeDecodeError: If there is an error decoding strings from\n"
" the target process");
#define _REMOTE_DEBUGGING_REMOTEUNWINDER_GET_STACK_TRACE_METHODDEF \
{"get_stack_trace", (PyCFunction)_remote_debugging_RemoteUnwinder_get_stack_trace, METH_NOARGS, _remote_debugging_RemoteUnwinder_get_stack_trace__doc__},
@ -279,20 +290,25 @@ PyDoc_STRVAR(_remote_debugging_RemoteUnwinder_get_all_awaited_by__doc__,
"\n"
"Get all tasks and their awaited_by relationships from the remote process.\n"
"\n"
"This provides a tree structure showing which tasks are waiting for other tasks.\n"
"This provides a tree structure showing which tasks are waiting for\n"
"other tasks.\n"
"\n"
"For each task, returns:\n"
"1. The call stack frames leading to where the task is currently executing\n"
"1. The call stack frames leading to where the task is currently\n"
" executing\n"
"2. The name of the task\n"
"3. A list of tasks that this task is waiting for, with their own frames/names/etc\n"
"3. A list of tasks that this task is waiting for, with their own\n"
" frames/names/etc\n"
"\n"
"Returns a list of [frames, task_name, subtasks] where:\n"
"- frames: List of (func_name, filename, lineno) showing the call stack\n"
"- frames: List of (func_name, filename, lineno) showing the call\n"
" stack\n"
"- task_name: String identifier for the task\n"
"- subtasks: List of tasks being awaited by this task, in same format\n"
"\n"
"Raises:\n"
" RuntimeError: If AsyncioDebug section is not available in the remote process\n"
" RuntimeError: If AsyncioDebug section is not available in the\n"
" remote process\n"
" MemoryError: If memory allocation fails\n"
" OSError: If reading from the remote process fails\n"
"\n"
@ -336,14 +352,16 @@ PyDoc_STRVAR(_remote_debugging_RemoteUnwinder_get_async_stack_trace__doc__,
"\n"
"Get the currently running async tasks and their dependency graphs from the remote process.\n"
"\n"
"This returns information about running tasks and all tasks that are waiting for them,\n"
"forming a complete dependency graph for each thread\'s active task.\n"
"This returns information about running tasks and all tasks that are\n"
"waiting for them, forming a complete dependency graph for each\n"
"thread\'s active task.\n"
"\n"
"For each thread with a running task, returns the running task plus all tasks that\n"
"transitively depend on it (tasks waiting for the running task, tasks waiting for\n"
"those tasks, etc.).\n"
"For each thread with a running task, returns the running task plus\n"
"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 contains:\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"
"\n"
@ -354,11 +372,13 @@ PyDoc_STRVAR(_remote_debugging_RemoteUnwinder_get_async_stack_trace__doc__,
"- List of tasks waiting for this task (recursive structure)\n"
"\n"
"Raises:\n"
" RuntimeError: If AsyncioDebug section is not available in the target process\n"
" RuntimeError: If AsyncioDebug section is not available in the\n"
" target process\n"
" 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 running tasks):\n"
"Example output (similar structure to get_all_awaited_by but only for\n"
"running tasks):\n"
"[\n"
" (140234, [\n"
" (4345585712, \'main_task\',\n"
@ -403,23 +423,34 @@ PyDoc_STRVAR(_remote_debugging_RemoteUnwinder_get_stats__doc__,
" - total_samples: Total number of get_stack_trace calls\n"
" - frame_cache_hits: Full cache hits (entire stack unchanged)\n"
" - frame_cache_misses: Cache misses requiring full walk\n"
" - frame_cache_partial_hits: Partial hits (stopped at cached frame)\n"
" - frame_cache_partial_hits: Partial hits (stopped at cached\n"
" frame)\n"
" - frames_read_from_cache: Total frames retrieved from cache\n"
" - frames_read_from_memory: Total frames read from remote memory\n"
" - frames_read_from_memory: Total frames read from remote\n"
" memory\n"
" - memory_reads: Total remote memory read operations\n"
" - memory_bytes_read: Total bytes read from remote memory\n"
" - code_object_cache_hits: Code object cache hits\n"
" - code_object_cache_misses: Code object cache misses\n"
" - stale_cache_invalidations: Times stale cache entries were cleared\n"
" - stale_cache_invalidations: Times stale cache entries were\n"
" cleared\n"
" - batched_read_attempts: Batched remote-read attempts\n"
" - batched_read_successes: Attempts that read all requested segments\n"
" - batched_read_misses: Attempts that fell back or partially read\n"
" - batched_read_segments_requested: Segments requested by batched reads\n"
" - batched_read_segments_completed: Segments completed by batched reads\n"
" - frame_cache_hit_rate: Percentage of samples that hit the cache\n"
" - code_object_cache_hit_rate: Percentage of code object lookups that hit cache\n"
" - batched_read_success_rate: Percentage of batched reads that completed all segments\n"
" - batched_read_segment_completion_rate: Percentage of requested segments read by batched reads\n"
" - batched_read_successes: Attempts that read all requested\n"
" segments\n"
" - batched_read_misses: Attempts that fell back or partially\n"
" read\n"
" - batched_read_segments_requested: Segments requested by\n"
" batched reads\n"
" - batched_read_segments_completed: Segments completed by\n"
" batched reads\n"
" - frame_cache_hit_rate: Percentage of samples that hit the\n"
" cache\n"
" - code_object_cache_hit_rate: Percentage of code object\n"
" lookups that hit cache\n"
" - batched_read_success_rate: Percentage of batched reads\n"
" that completed all segments\n"
" - batched_read_segment_completion_rate: Percentage of\n"
" requested segments read by batched reads\n"
"\n"
"Raises:\n"
" RuntimeError: If stats collection was not enabled (stats=False)");
@ -449,9 +480,11 @@ PyDoc_STRVAR(_remote_debugging_RemoteUnwinder_pause_threads__doc__,
"Pause all threads in the target process.\n"
"\n"
"This stops all threads in the target process to allow for consistent\n"
"memory reads during sampling. Must be paired with a call to resume_threads().\n"
"memory reads during sampling. Must be paired with a call to\n"
"resume_threads().\n"
"\n"
"Returns True if threads were successfully paused, False if they were already paused.\n"
"Returns True if threads were successfully paused, False if they were\n"
"already paused.\n"
"\n"
"Raises:\n"
" RuntimeError: If there is an error stopping the threads");
@ -480,9 +513,11 @@ PyDoc_STRVAR(_remote_debugging_RemoteUnwinder_resume_threads__doc__,
"\n"
"Resume all threads in the target process.\n"
"\n"
"This resumes threads that were previously paused with pause_threads().\n"
"This resumes threads that were previously paused with\n"
"pause_threads().\n"
"\n"
"Returns True if threads were successfully resumed, False if they were not paused.");
"Returns True if threads were successfully resumed, False if they\n"
"were not paused.");
#define _REMOTE_DEBUGGING_REMOTEUNWINDER_RESUME_THREADS_METHODDEF \
{"resume_threads", (PyCFunction)_remote_debugging_RemoteUnwinder_resume_threads, METH_NOARGS, _remote_debugging_RemoteUnwinder_resume_threads__doc__},
@ -510,16 +545,18 @@ PyDoc_STRVAR(_remote_debugging_GCMonitor___init____doc__,
"\n"
"Args:\n"
" pid: Process ID of the target Python process to monitor\n"
" debug: If True, chain exceptions to explain the sequence of events that\n"
" lead to the exception.\n"
" debug: If True, chain exceptions to explain the sequence of\n"
" events that lead to the exception.\n"
"\n"
"The GCMonitor provides functionality to read GC statistics from a running\n"
"Python process.\n"
"The GCMonitor provides functionality to read GC statistics from\n"
"a running Python process.\n"
"\n"
"Raises:\n"
" PermissionError: If access to the target process is denied\n"
" OSError: If unable to attach to the target process or access its memory\n"
" RuntimeError: If unable to read debug information from the target process");
" OSError: If unable to attach to the target process or access\n"
" its memory\n"
" RuntimeError: If unable to read debug information from the\n"
" target process");
static int
_remote_debugging_GCMonitor___init___impl(GCMonitorObject *self, int pid,
@ -612,8 +649,8 @@ PyDoc_STRVAR(_remote_debugging_GCMonitor_get_gc_stats__doc__,
" - duration: Total collection time, in seconds.\n"
"\n"
"Raises:\n"
" RuntimeError: If the target process cannot be inspected or if its\n"
" debug offsets or GC stats layout are incompatible.");
" RuntimeError: If the target process cannot be inspected or if\n"
" its debug offsets or GC stats layout are incompatible.");
#define _REMOTE_DEBUGGING_GCMONITOR_GET_GC_STATS_METHODDEF \
{"get_gc_stats", _PyCFunction_CAST(_remote_debugging_GCMonitor_get_gc_stats), METH_FASTCALL|METH_KEYWORDS, _remote_debugging_GCMonitor_get_gc_stats__doc__},
@ -688,7 +725,8 @@ PyDoc_STRVAR(_remote_debugging_BinaryWriter___init____doc__,
"Arguments:\n"
" filename: Path to output file\n"
" sample_interval_us: Sampling interval in microseconds\n"
" start_time_us: Start timestamp in microseconds (from time.monotonic() * 1e6)\n"
" start_time_us: Start timestamp in microseconds (from\n"
" time.monotonic() * 1e6)\n"
" compression: 0=none, 1=zstd (default: 0)\n"
"\n"
"Use as a context manager or call finalize() when done.");
@ -774,7 +812,8 @@ PyDoc_STRVAR(_remote_debugging_BinaryWriter_write_sample__doc__,
"\n"
"Arguments:\n"
" stack_frames: List of InterpreterInfo objects\n"
" timestamp_us: Current timestamp in microseconds (from time.monotonic() * 1e6)");
" timestamp_us: Current timestamp in microseconds (from\n"
" time.monotonic() * 1e6)");
#define _REMOTE_DEBUGGING_BINARYWRITER_WRITE_SAMPLE_METHODDEF \
{"write_sample", _PyCFunction_CAST(_remote_debugging_BinaryWriter_write_sample), METH_FASTCALL|METH_KEYWORDS, _remote_debugging_BinaryWriter_write_sample__doc__},
@ -976,8 +1015,9 @@ PyDoc_STRVAR(_remote_debugging_BinaryWriter_get_stats__doc__,
"\n"
"Get encoding statistics for the writer.\n"
"\n"
"Returns a dict with encoding statistics including repeat/full/suffix/pop-push\n"
"record counts, frames written/saved, and compression ratio.");
"Returns a dict with encoding statistics including\n"
"repeat/full/suffix/pop-push record counts, frames written/saved, and\n"
"compression ratio.");
#define _REMOTE_DEBUGGING_BINARYWRITER_GET_STATS_METHODDEF \
{"get_stats", (PyCFunction)_remote_debugging_BinaryWriter_get_stats, METH_NOARGS, _remote_debugging_BinaryWriter_get_stats__doc__},
@ -1155,8 +1195,8 @@ PyDoc_STRVAR(_remote_debugging_BinaryReader_get_stats__doc__,
"\n"
"Get reconstruction statistics from replay.\n"
"\n"
"Returns a dict with statistics about record types decoded and samples\n"
"reconstructed during replay.");
"Returns a dict with statistics about record types decoded and\n"
"samples reconstructed during replay.");
#define _REMOTE_DEBUGGING_BINARYREADER_GET_STATS_METHODDEF \
{"get_stats", (PyCFunction)_remote_debugging_BinaryReader_get_stats, METH_NOARGS, _remote_debugging_BinaryReader_get_stats__doc__},
@ -1319,11 +1359,12 @@ PyDoc_STRVAR(_remote_debugging_get_child_pids__doc__,
" If True, return all descendants (children, grandchildren, etc.).\n"
" If False, return only direct children.\n"
"\n"
"Returns a list of child process IDs. Returns an empty list if no children\n"
"are found.\n"
"Returns a list of child process IDs. Returns an empty list if no\n"
"children are found.\n"
"\n"
"This function provides a snapshot of child processes at a moment in time.\n"
"Child processes may exit or new ones may be created after the list is returned.\n"
"This function provides a snapshot of child processes at a moment in\n"
"time. Child processes may exit or new ones may be created after the\n"
"list is returned.\n"
"\n"
"Raises:\n"
" OSError: If unable to enumerate processes\n"
@ -1547,4 +1588,4 @@ skip_optional_kwonly:
exit:
return return_value;
}
/*[clinic end generated code: output=884914b100e9c90c input=a9049054013a1b77]*/
/*[clinic end generated code: output=a3df14a6ab7f2998 input=a9049054013a1b77]*/

View file

@ -280,7 +280,6 @@ class _remote_debugging.RemoteUnwinder "RemoteUnwinderObject *" "&RemoteUnwinder
/*[clinic input]
@permit_long_summary
@permit_long_docstring_body
_remote_debugging.RemoteUnwinder.__init__
pid: int
*
@ -299,33 +298,37 @@ Initialize a new RemoteUnwinder object for debugging a remote Python process.
Args:
pid: Process ID of the target Python process to debug
all_threads: If True, initialize state for all threads in the process.
If False, only initialize for the main thread.
all_threads: If True, initialize state for all threads in the
process. If False, only initialize for the main thread.
only_active_thread: If True, only sample the thread holding the GIL.
mode: Profiling mode: 0=WALL (wall-time), 1=CPU (cpu-time), 2=GIL (gil-time).
Cannot be used together with all_threads=True.
debug: If True, chain exceptions to explain the sequence of events that
lead to the exception.
skip_non_matching_threads: If True, skip threads that don't match the selected mode.
If False, include all threads regardless of mode.
native: If True, include artificial "<native>" frames to denote calls to
non-Python code.
gc: If True, include artificial "<GC>" frames to denote active garbage
collection.
opcodes: If True, gather bytecode opcode information for instruction-level
profiling.
cache_frames: If True, enable frame caching optimization to avoid re-reading
unchanged parent frames between samples.
stats: If True, collect statistics about cache hits, memory reads, etc.
Use get_stats() to retrieve the collected statistics.
mode: Profiling mode: 0=WALL (wall-time), 1=CPU (cpu-time), 2=GIL
(gil-time). Cannot be used together with all_threads=True.
debug: If True, chain exceptions to explain the sequence of events
that lead to the exception.
skip_non_matching_threads: If True, skip threads that don't match
the selected mode. If False, include all threads regardless of
mode.
native: If True, include artificial "<native>" frames to denote
calls to non-Python code.
gc: If True, include artificial "<GC>" frames to denote active
garbage collection.
opcodes: If True, gather bytecode opcode information for
instruction-level profiling.
cache_frames: If True, enable frame caching optimization to avoid
re-reading unchanged parent frames between samples.
stats: If True, collect statistics about cache hits, memory reads,
etc. Use get_stats() to retrieve the collected statistics.
The RemoteUnwinder provides functionality to inspect and debug a running Python
process, including examining thread states, stack frames and other runtime data.
The RemoteUnwinder provides functionality to inspect and debug a running
Python process, including examining thread states, stack frames and
other runtime data.
Raises:
PermissionError: If access to the target process is denied
OSError: If unable to attach to the target process or access its memory
RuntimeError: If unable to read debug information from the target process
OSError: If unable to attach to the target process or access its
memory
RuntimeError: If unable to read debug information from the target
process
ValueError: If both all_threads and only_active_thread are True
[clinic start generated code]*/
@ -338,7 +341,7 @@ _remote_debugging_RemoteUnwinder___init___impl(RemoteUnwinderObject *self,
int native, int gc,
int opcodes, int cache_frames,
int stats)
/*[clinic end generated code: output=0031f743f4b9ad52 input=8fb61b24102dec6e]*/
/*[clinic end generated code: output=0031f743f4b9ad52 input=9d25ae328d62626d]*/
{
// Validate that all_threads and only_active_thread are not both True
if (all_threads && only_active_thread) {
@ -645,22 +648,26 @@ read_interp_state_and_maybe_thread_frame(
}
/*[clinic input]
@permit_long_docstring_body
@critical_section
_remote_debugging.RemoteUnwinder.get_stack_trace
Returns stack traces for all interpreters and threads in process.
Each element in the returned list is a tuple of (interpreter_id, thread_list), where:
Each element in the returned list is a tuple of (interpreter_id,
thread_list), where:
- interpreter_id is the interpreter identifier
- thread_list is a list of tuples (thread_id, frame_list) for threads in that interpreter
- thread_list is a list of tuples (thread_id, frame_list) for
threads in that interpreter
- thread_id is the OS thread identifier
- frame_list is a list of tuples (function_name, filename, line_number) representing
the Python stack frames for that thread, ordered from most recent to oldest
- frame_list is a list of tuples (function_name, filename,
line_number) representing the Python stack frames for that
thread, ordered from most recent to oldest
The threads returned depend on the initialization parameters:
- If only_active_thread was True: returns only the thread holding the GIL across all interpreters
- If all_threads was True: returns all threads across all interpreters
- If only_active_thread was True: returns only the thread holding
the GIL across all interpreters
- If all_threads was True: returns all threads across all
interpreters
- Otherwise: returns only the main thread of each interpreter
Example:
@ -684,16 +691,18 @@ The threads returned depend on the initialization parameters:
]
Raises:
RuntimeError: If there is an error copying memory from the target process
RuntimeError: If there is an error copying memory from the
target process
OSError: If there is an error accessing the target process
PermissionError: If access to the target process is denied
UnicodeDecodeError: If there is an error decoding strings from the target process
UnicodeDecodeError: If there is an error decoding strings from
the target process
[clinic start generated code]*/
static PyObject *
_remote_debugging_RemoteUnwinder_get_stack_trace_impl(RemoteUnwinderObject *self)
/*[clinic end generated code: output=666192b90c69d567 input=bcff01c73cccc1c0]*/
/*[clinic end generated code: output=666192b90c69d567 input=86a992b853f48aa9]*/
{
STATS_INC(self, total_samples);
@ -893,26 +902,30 @@ _remote_debugging_RemoteUnwinder_get_stack_trace_impl(RemoteUnwinderObject *self
/*[clinic input]
@permit_long_summary
@permit_long_docstring_body
@critical_section
_remote_debugging.RemoteUnwinder.get_all_awaited_by
Get all tasks and their awaited_by relationships from the remote process.
This provides a tree structure showing which tasks are waiting for other tasks.
This provides a tree structure showing which tasks are waiting for
other tasks.
For each task, returns:
1. The call stack frames leading to where the task is currently executing
1. The call stack frames leading to where the task is currently
executing
2. The name of the task
3. A list of tasks that this task is waiting for, with their own frames/names/etc
3. A list of tasks that this task is waiting for, with their own
frames/names/etc
Returns a list of [frames, task_name, subtasks] where:
- frames: List of (func_name, filename, lineno) showing the call stack
- frames: List of (func_name, filename, lineno) showing the call
stack
- task_name: String identifier for the task
- subtasks: List of tasks being awaited by this task, in same format
Raises:
RuntimeError: If AsyncioDebug section is not available in the remote process
RuntimeError: If AsyncioDebug section is not available in the
remote process
MemoryError: If memory allocation fails
OSError: If reading from the remote process fails
@ -939,7 +952,7 @@ Example output:
static PyObject *
_remote_debugging_RemoteUnwinder_get_all_awaited_by_impl(RemoteUnwinderObject *self)
/*[clinic end generated code: output=6a49cd345e8aec53 input=307f754cbe38250c]*/
/*[clinic end generated code: output=6a49cd345e8aec53 input=c22bfee0612e0b69]*/
{
if (ensure_async_debug_offsets(self) < 0) {
return NULL;
@ -984,20 +997,21 @@ _remote_debugging_RemoteUnwinder_get_all_awaited_by_impl(RemoteUnwinderObject *s
/*[clinic input]
@permit_long_summary
@permit_long_docstring_body
@critical_section
_remote_debugging.RemoteUnwinder.get_async_stack_trace
Get the currently running async tasks and their dependency graphs from the remote process.
This returns information about running tasks and all tasks that are waiting for them,
forming a complete dependency graph for each thread's active task.
This returns information about running tasks and all tasks that are
waiting for them, forming a complete dependency graph for each
thread's active task.
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.).
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:
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
@ -1008,11 +1022,13 @@ Each task info contains:
- List of tasks waiting for this task (recursive structure)
Raises:
RuntimeError: If AsyncioDebug section is not available in the target process
RuntimeError: If AsyncioDebug section is not available in the
target process
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):
Example output (similar structure to get_all_awaited_by but only for
running tasks):
[
# Thread 140234 results
(140234, [
@ -1031,7 +1047,7 @@ Example output (similar structure to get_all_awaited_by but only for running tas
static PyObject *
_remote_debugging_RemoteUnwinder_get_async_stack_trace_impl(RemoteUnwinderObject *self)
/*[clinic end generated code: output=6433d52b55e87bbe input=6129b7d509a887c9]*/
/*[clinic end generated code: output=6433d52b55e87bbe input=bc802e4221c99399]*/
{
if (ensure_async_debug_offsets(self) < 0) {
return NULL;
@ -1060,7 +1076,6 @@ _remote_debugging_RemoteUnwinder_get_async_stack_trace_impl(RemoteUnwinderObject
}
/*[clinic input]
@permit_long_docstring_body
@critical_section
_remote_debugging.RemoteUnwinder.get_stats
@ -1075,23 +1090,34 @@ RemoteUnwinder was created with stats=True.
- total_samples: Total number of get_stack_trace calls
- frame_cache_hits: Full cache hits (entire stack unchanged)
- frame_cache_misses: Cache misses requiring full walk
- frame_cache_partial_hits: Partial hits (stopped at cached frame)
- frame_cache_partial_hits: Partial hits (stopped at cached
frame)
- frames_read_from_cache: Total frames retrieved from cache
- frames_read_from_memory: Total frames read from remote memory
- frames_read_from_memory: Total frames read from remote
memory
- memory_reads: Total remote memory read operations
- memory_bytes_read: Total bytes read from remote memory
- code_object_cache_hits: Code object cache hits
- code_object_cache_misses: Code object cache misses
- stale_cache_invalidations: Times stale cache entries were cleared
- stale_cache_invalidations: Times stale cache entries were
cleared
- batched_read_attempts: Batched remote-read attempts
- batched_read_successes: Attempts that read all requested segments
- batched_read_misses: Attempts that fell back or partially read
- batched_read_segments_requested: Segments requested by batched reads
- batched_read_segments_completed: Segments completed by batched reads
- frame_cache_hit_rate: Percentage of samples that hit the cache
- code_object_cache_hit_rate: Percentage of code object lookups that hit cache
- batched_read_success_rate: Percentage of batched reads that completed all segments
- batched_read_segment_completion_rate: Percentage of requested segments read by batched reads
- batched_read_successes: Attempts that read all requested
segments
- batched_read_misses: Attempts that fell back or partially
read
- batched_read_segments_requested: Segments requested by
batched reads
- batched_read_segments_completed: Segments completed by
batched reads
- frame_cache_hit_rate: Percentage of samples that hit the
cache
- code_object_cache_hit_rate: Percentage of code object
lookups that hit cache
- batched_read_success_rate: Percentage of batched reads
that completed all segments
- batched_read_segment_completion_rate: Percentage of
requested segments read by batched reads
Raises:
RuntimeError: If stats collection was not enabled (stats=False)
@ -1099,7 +1125,7 @@ RemoteUnwinder was created with stats=True.
static PyObject *
_remote_debugging_RemoteUnwinder_get_stats_impl(RemoteUnwinderObject *self)
/*[clinic end generated code: output=21e36477122be2a0 input=0392d62b278e9c35]*/
/*[clinic end generated code: output=21e36477122be2a0 input=87905c65038fb06e]*/
{
if (!self->collect_stats) {
PyErr_SetString(PyExc_RuntimeError,
@ -1192,16 +1218,17 @@ _remote_debugging_RemoteUnwinder_get_stats_impl(RemoteUnwinderObject *self)
}
/*[clinic input]
@permit_long_docstring_body
@critical_section
_remote_debugging.RemoteUnwinder.pause_threads
Pause all threads in the target process.
This stops all threads in the target process to allow for consistent
memory reads during sampling. Must be paired with a call to resume_threads().
memory reads during sampling. Must be paired with a call to
resume_threads().
Returns True if threads were successfully paused, False if they were already paused.
Returns True if threads were successfully paused, False if they were
already paused.
Raises:
RuntimeError: If there is an error stopping the threads
@ -1209,7 +1236,7 @@ Returns True if threads were successfully paused, False if they were already pau
static PyObject *
_remote_debugging_RemoteUnwinder_pause_threads_impl(RemoteUnwinderObject *self)
/*[clinic end generated code: output=aaf2bdc0a725750c input=d8a266f19a81c67e]*/
/*[clinic end generated code: output=aaf2bdc0a725750c input=b91dde5517c9dde2]*/
{
#ifdef Py_REMOTE_DEBUG_SUPPORTS_BLOCKING
if (self->threads_stopped) {
@ -1231,20 +1258,21 @@ _remote_debugging_RemoteUnwinder_pause_threads_impl(RemoteUnwinderObject *self)
}
/*[clinic input]
@permit_long_docstring_body
@critical_section
_remote_debugging.RemoteUnwinder.resume_threads
Resume all threads in the target process.
This resumes threads that were previously paused with pause_threads().
This resumes threads that were previously paused with
pause_threads().
Returns True if threads were successfully resumed, False if they were not paused.
Returns True if threads were successfully resumed, False if they
were not paused.
[clinic start generated code]*/
static PyObject *
_remote_debugging_RemoteUnwinder_resume_threads_impl(RemoteUnwinderObject *self)
/*[clinic end generated code: output=8d6781ea37095536 input=16baaaab007f4259]*/
/*[clinic end generated code: output=8d6781ea37095536 input=130758d55d46897a]*/
{
#ifdef Py_REMOTE_DEBUG_SUPPORTS_BLOCKING
if (!self->threads_stopped) {
@ -1382,7 +1410,6 @@ class _remote_debugging.GCMonitor "GCMonitorObject *" "&GCMonitor_Type"
/*[clinic input]
@permit_long_summary
@permit_long_docstring_body
_remote_debugging.GCMonitor.__init__
pid: int
*
@ -1392,22 +1419,24 @@ Initialize a new GCMonitor object for monitoring GC events from remote process.
Args:
pid: Process ID of the target Python process to monitor
debug: If True, chain exceptions to explain the sequence of events that
lead to the exception.
debug: If True, chain exceptions to explain the sequence of
events that lead to the exception.
The GCMonitor provides functionality to read GC statistics from a running
Python process.
The GCMonitor provides functionality to read GC statistics from
a running Python process.
Raises:
PermissionError: If access to the target process is denied
OSError: If unable to attach to the target process or access its memory
RuntimeError: If unable to read debug information from the target process
OSError: If unable to attach to the target process or access
its memory
RuntimeError: If unable to read debug information from the
target process
[clinic start generated code]*/
static int
_remote_debugging_GCMonitor___init___impl(GCMonitorObject *self, int pid,
int debug)
/*[clinic end generated code: output=2cdf351c2f6335db input=1185a48535b808be]*/
/*[clinic end generated code: output=2cdf351c2f6335db input=03da0b2d3282ae1b]*/
{
return init_runtime_offsets(&self->offsets, pid, debug);
}
@ -1438,14 +1467,14 @@ Returns a list of GCStatsInfo objects with GC statistics data.
- duration: Total collection time, in seconds.
Raises:
RuntimeError: If the target process cannot be inspected or if its
debug offsets or GC stats layout are incompatible.
RuntimeError: If the target process cannot be inspected or if
its debug offsets or GC stats layout are incompatible.
[clinic start generated code]*/
static PyObject *
_remote_debugging_GCMonitor_get_gc_stats_impl(GCMonitorObject *self,
int all_interpreters)
/*[clinic end generated code: output=f73f365725224f7a input=12f7c1a288cf2741]*/
/*[clinic end generated code: output=f73f365725224f7a input=ec016bc4be6dd003]*/
{
RemoteDebuggingState *st = RemoteDebugging_GetStateFromType(Py_TYPE(self));
return get_gc_stats(&self->offsets, all_interpreters, st->GCStatsInfo_Type);
@ -1682,7 +1711,6 @@ class _remote_debugging.BinaryWriter "BinaryWriterObject *" "&PyBinaryWriter_Typ
/*[clinic end generated code: output=da39a3ee5e6b4b0d input=e948838b90a2003c]*/
/*[clinic input]
@permit_long_docstring_body
_remote_debugging.BinaryWriter.__init__
filename: object
sample_interval_us: unsigned_long_long
@ -1695,7 +1723,8 @@ High-performance binary writer for profiling data.
Arguments:
filename: Path to output file
sample_interval_us: Sampling interval in microseconds
start_time_us: Start timestamp in microseconds (from time.monotonic() * 1e6)
start_time_us: Start timestamp in microseconds (from
time.monotonic() * 1e6)
compression: 0=none, 1=zstd (default: 0)
Use as a context manager or call finalize() when done.
@ -1707,7 +1736,7 @@ _remote_debugging_BinaryWriter___init___impl(BinaryWriterObject *self,
unsigned long long sample_interval_us,
unsigned long long start_time_us,
int compression)
/*[clinic end generated code: output=00446656ea2e5986 input=b92f0c77ba4cd274]*/
/*[clinic end generated code: output=00446656ea2e5986 input=2e3f298c69fc7666]*/
{
if (self->writer) {
binary_writer_destroy(self->writer);
@ -1722,7 +1751,6 @@ _remote_debugging_BinaryWriter___init___impl(BinaryWriterObject *self,
}
/*[clinic input]
@permit_long_docstring_body
_remote_debugging.BinaryWriter.write_sample
stack_frames: object
timestamp_us: unsigned_long_long
@ -1731,14 +1759,15 @@ Write a sample to the binary file.
Arguments:
stack_frames: List of InterpreterInfo objects
timestamp_us: Current timestamp in microseconds (from time.monotonic() * 1e6)
timestamp_us: Current timestamp in microseconds (from
time.monotonic() * 1e6)
[clinic start generated code]*/
static PyObject *
_remote_debugging_BinaryWriter_write_sample_impl(BinaryWriterObject *self,
PyObject *stack_frames,
unsigned long long timestamp_us)
/*[clinic end generated code: output=24d5b86679b4128f input=4e6d832d360bea46]*/
/*[clinic end generated code: output=24d5b86679b4128f input=5033f1ae7fa135f1]*/
{
if (!self->writer) {
PyErr_SetString(PyExc_ValueError, "Writer is closed");
@ -1861,18 +1890,18 @@ _remote_debugging_BinaryWriter___exit___impl(BinaryWriterObject *self,
}
/*[clinic input]
@permit_long_docstring_body
_remote_debugging.BinaryWriter.get_stats
Get encoding statistics for the writer.
Returns a dict with encoding statistics including repeat/full/suffix/pop-push
record counts, frames written/saved, and compression ratio.
Returns a dict with encoding statistics including
repeat/full/suffix/pop-push record counts, frames written/saved, and
compression ratio.
[clinic start generated code]*/
static PyObject *
_remote_debugging_BinaryWriter_get_stats_impl(BinaryWriterObject *self)
/*[clinic end generated code: output=06522cd52544df89 input=837c874ffdebd24c]*/
/*[clinic end generated code: output=06522cd52544df89 input=a8bb8c8682ccd34b]*/
{
if (!self->writer) {
PyErr_SetString(PyExc_ValueError, "Writer is closed");
@ -2037,13 +2066,13 @@ _remote_debugging.BinaryReader.get_stats
Get reconstruction statistics from replay.
Returns a dict with statistics about record types decoded and samples
reconstructed during replay.
Returns a dict with statistics about record types decoded and
samples reconstructed during replay.
[clinic start generated code]*/
static PyObject *
_remote_debugging_BinaryReader_get_stats_impl(BinaryReaderObject *self)
/*[clinic end generated code: output=628b9ab5e4c4fd36 input=d8dd6654abd6c3c0]*/
/*[clinic end generated code: output=628b9ab5e4c4fd36 input=15b8d8f89ccf3726]*/
{
if (!self->reader) {
PyErr_SetString(PyExc_ValueError, "Reader is closed");
@ -2195,7 +2224,6 @@ _remote_debugging_zstd_available_impl(PyObject *module)
* ============================================================================ */
/*[clinic input]
@permit_long_docstring_body
_remote_debugging.get_child_pids
pid: int
@ -2207,11 +2235,12 @@ _remote_debugging.get_child_pids
Get all child process IDs of the given process.
Returns a list of child process IDs. Returns an empty list if no children
are found.
Returns a list of child process IDs. Returns an empty list if no
children are found.
This function provides a snapshot of child processes at a moment in time.
Child processes may exit or new ones may be created after the list is returned.
This function provides a snapshot of child processes at a moment in
time. Child processes may exit or new ones may be created after the
list is returned.
Raises:
OSError: If unable to enumerate processes
@ -2221,7 +2250,7 @@ Child processes may exit or new ones may be created after the list is returned.
static PyObject *
_remote_debugging_get_child_pids_impl(PyObject *module, int pid,
int recursive)
/*[clinic end generated code: output=1ae2289c6b953e4b input=19d8d5d6e2b59e6e]*/
/*[clinic end generated code: output=1ae2289c6b953e4b input=c6437b52e2fdd880]*/
{
return enumerate_child_pids((pid_t)pid, recursive);
}