Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
903a3d3
remap
maurycy Jun 3, 2026
a212263
no kind for now
maurycy Jun 3, 2026
57ccb8d
simpler
maurycy Jun 3, 2026
155a33d
do not continue if the probe failed
maurycy Jun 3, 2026
fc6e951
left-over
maurycy Jun 3, 2026
aaea3ab
this is implicit from the RemoteUnwinder
maurycy Jun 3, 2026
f3aa1b7
use _Py_RemoteDebug_ReadRemoteMemory directly
maurycy Jun 3, 2026
8b18ea0
disable on remap failure immediately
maurycy Jun 3, 2026
f84d595
dedup `AliasProbe` and `alias_remap_page`
maurycy Jun 3, 2026
12fb871
FreeBSD style!
maurycy Jun 3, 2026
f37e525
make clinic, expected_parent is macos-only
maurycy Jun 4, 2026
9d65148
stop abusing stats for debugging
maurycy Jun 4, 2026
d4c86ff
lazy fail is ok
maurycy Jun 4, 2026
059f116
avoid seq scan in lru; try a set
maurycy Jun 4, 2026
1a7e06f
Revert "avoid seq scan in lru; try a set"
maurycy Jun 4, 2026
a0a330a
there's task_info, no need to rely on pid+ts
maurycy Jun 9, 2026
076f722
never observed stale interp in the wild
maurycy Jun 9, 2026
e3c1953
mach_port_type...
maurycy Jun 9, 2026
5e8d23e
notify about death
maurycy Jun 9, 2026
69d8825
mach_vm_remap(FIXED|OVERWRITE)
maurycy Jun 9, 2026
d53f4e5
Revert "notify about death"
maurycy Jun 9, 2026
a2aec47
NEVER happened in the wild, across 47m samples with lots of churn;
maurycy Jun 9, 2026
d02e640
poor man's AIMD mach_vm_region_recurse()
maurycy Jun 9, 2026
a3c9e25
0/800m calls w/ very churny scenarios
maurycy Jun 10, 2026
74e4973
interp_window_{start,size}; 3.4MHz
maurycy Jun 10, 2026
d2477bd
vm_max_address
maurycy Jun 10, 2026
52b4751
some love
maurycy Jun 10, 2026
496d439
dead prefetch computation on macos
maurycy Jun 10, 2026
8f39212
do it well, it's now confirmed to bring 3.4-3.6Mhz
maurycy Jun 10, 2026
6ace38b
build warning
maurycy Jun 10, 2026
d44e81d
harden
maurycy Jun 10, 2026
972f5f7
disable if target != local vm size
maurycy Jun 10, 2026
aa96048
invalid frame != stale map
maurycy Jun 10, 2026
64502de
probe check
maurycy Jun 10, 2026
199e75d
do not disable permanently on a single remap fail
maurycy Jun 10, 2026
40cf8a3
KERN_NOT_SUPPORTED + fix stats
maurycy Jun 10, 2026
69eaabf
better stats, better err handling
maurycy Jun 11, 2026
b226e60
dead code
maurycy Jun 11, 2026
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
7 changes: 7 additions & 0 deletions Lib/test/test_external_inspection.py
Original file line number Diff line number Diff line change
Expand Up @@ -3772,6 +3772,13 @@ def test_get_stats(self):
"batched_read_misses",
"batched_read_segments_requested",
"batched_read_segments_completed",
"alias_hits",
"alias_misses",
"alias_remap_failures",
"alias_validation_fails",
"alias_evictions",
"alias_probe_checks",
"alias_probe_recycles",
"batched_read_success_rate",
"batched_read_segment_completion_rate",
]
Expand Down
2 changes: 1 addition & 1 deletion Modules/Setup.stdlib.in
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@
@MODULE__PICKLE_TRUE@_pickle _pickle.c
@MODULE__QUEUE_TRUE@_queue _queuemodule.c
@MODULE__RANDOM_TRUE@_random _randommodule.c
@MODULE__REMOTE_DEBUGGING_TRUE@_remote_debugging _remote_debugging/module.c _remote_debugging/gc_stats.c _remote_debugging/object_reading.c _remote_debugging/code_objects.c _remote_debugging/frames.c _remote_debugging/frame_cache.c _remote_debugging/threads.c _remote_debugging/asyncio.c _remote_debugging/binary_io_writer.c _remote_debugging/binary_io_reader.c _remote_debugging/subprocess.c _remote_debugging/interpreters.c
@MODULE__REMOTE_DEBUGGING_TRUE@_remote_debugging _remote_debugging/module.c _remote_debugging/gc_stats.c _remote_debugging/object_reading.c _remote_debugging/code_objects.c _remote_debugging/frames.c _remote_debugging/frame_cache.c _remote_debugging/threads.c _remote_debugging/asyncio.c _remote_debugging/alias_read.c _remote_debugging/binary_io_writer.c _remote_debugging/binary_io_reader.c _remote_debugging/subprocess.c _remote_debugging/interpreters.c
@MODULE__STRUCT_TRUE@_struct _struct.c

# build supports subinterpreters
Expand Down
60 changes: 60 additions & 0 deletions Modules/_remote_debugging/_remote_debugging.h
Original file line number Diff line number Diff line change
Expand Up @@ -262,6 +262,31 @@ typedef struct {
uintptr_t frame_addr;
} RemoteReadPrefetch;

#if defined(__APPLE__) && TARGET_OS_OSX
#define MAX_ALIAS_PAGES 256
#define ALIAS_PROBE_DEFAULT_MASK 0x3ff
#define ALIAS_PROBE_MIN_MASK 0x3f
#define ALIAS_PROBE_MAX_MASK 0x3fff

typedef struct {
uintptr_t remote_page_base;
mach_vm_address_t local_page_base;
uint64_t access_seq;
int valid;
uint64_t map_objid;
uint64_t map_offset;
} AliasPageEntry;

typedef struct {
AliasPageEntry pages[MAX_ALIAS_PAGES];
mach_vm_address_t region_base;
uint64_t access_seq;
uint32_t probe_counter;
uint32_t probe_mask;
int disabled;
} AliasReadCache;
#endif

/* Statistics for profiling performance analysis */
typedef struct {
uint64_t total_samples; // Total number of get_stack_trace calls
Expand All @@ -280,6 +305,13 @@ typedef struct {
uint64_t batched_read_misses; // Attempts that fell back or partially read
uint64_t batched_read_segments_requested; // Segments requested by batched reads
uint64_t batched_read_segments_completed; // Segments completed by batched reads
uint64_t alias_hits; // macOS alias-cache hits
uint64_t alias_misses; // macOS alias-cache misses
uint64_t alias_remap_failures; // macOS remap/protect failures
uint64_t alias_validation_fails; // macOS alias snapshot validation failures
uint64_t alias_evictions; // macOS alias-cache LRU evictions
uint64_t alias_probe_checks; // macOS alias object identity probes
uint64_t alias_probe_recycles; // macOS alias recycled-page detections
} UnwinderStats;

#if defined(__GNUC__) || defined(__clang__)
Expand Down Expand Up @@ -349,6 +381,9 @@ typedef struct {
proc_handle_t handle;
uintptr_t runtime_start_address;
struct _Py_DebugOffsets debug_offsets;
size_t interp_window_start;
size_t interp_window_size;
uintptr_t vm_max_address;
int async_debug_offsets_available;
struct _Py_AsyncioModuleDebugOffsets async_debug_offsets;
uintptr_t interpreter_addr;
Expand Down Expand Up @@ -382,6 +417,9 @@ typedef struct {
#ifdef __APPLE__
uint64_t thread_id_offset;
int thread_id_offset_initialized;
# if TARGET_OS_OSX
AliasReadCache alias_cache;
# endif
#endif
#ifdef MS_WINDOWS
PVOID win_process_buffer;
Expand Down Expand Up @@ -648,6 +686,27 @@ extern int collect_frames_with_cache(
FrameWalkContext *ctx,
uint64_t thread_id);

#if defined(__APPLE__) && TARGET_OS_OSX

extern int _Py_RemoteDebug_ValidateThreadStateSnapshot(
RemoteUnwinderObject *unwinder,
const char *tstate_buffer,
uintptr_t tstate_addr,
uintptr_t current_interpreter
);
/* Returns 0 if bytes were served from an aliased page snapshot (callers
* should validate), 1 if no snapshot was involved (live syscall read or
* zero-length no-op; skip validation), -1 on error with an exception
* set. */
extern int _Py_RemoteDebug_AliasedRead(
RemoteUnwinderObject *unwinder,
uintptr_t remote_addr,
size_t len,
void *dst);
extern void _Py_RemoteDebug_AliasCacheInit(RemoteUnwinderObject *unwinder);
extern void _Py_RemoteDebug_AliasCacheClear(RemoteUnwinderObject *unwinder);
#endif

/* ============================================================================
* THREAD FUNCTION DECLARATIONS
* ============================================================================ */
Expand Down Expand Up @@ -676,6 +735,7 @@ extern int get_thread_status(RemoteUnwinderObject *unwinder, uint64_t tid, uint6

extern PyObject* unwind_stack_for_thread(
RemoteUnwinderObject *unwinder,
uintptr_t current_interpreter,
uintptr_t *current_tstate,
uintptr_t gil_holder_tstate,
uintptr_t gc_frame,
Expand Down
Loading
Loading