gh-151613: Fix remote debugging frame cache ABA#151614
Conversation
000eedb to
9f447d8
Compare
418a947 to
a548b24
Compare
Fixes python#151613. The remote debugging frame cache previously used only the last_profiled_frame address as its cache anchor. If a frame returned and a later frame reused the same _PyInterpreterFrame address, the profiler could accept a stale cache entry and splice parent frames from a different call chain into the current stack. This adds a last_profiled_frame_seq counter next to last_profiled_frame, increments it when the anchor advances, stores it in frame cache entries, and validates cache hits against both the frame address and the sequence. Cache miss walks now copy stack chunks before storing new cache entries so stored continuations come from a stable snapshot. The new regression test exercises alternating call chains and checks that cached stacks never contain frames from both branches.
a548b24 to
fc9fafd
Compare
|
Discussed this a bit with @maurycy offline. I’m going to keep this PR as the small ABA/cache-anchor fix. The sequence here is tied to The epoch idea where we bump on any pop while profiling is active is useful to explore, but it changes the meaning of the counter and makes the cache more conservative. I think that should be a follow-up with the Oracle data and perf/cache-hit numbers. I’m also dropping the new test from |
|
Thanks @pablogsal for the PR 🌮🎉.. I'm working now to backport this PR to: 3.15. |
|
Sorry, @pablogsal, I could not cleanly backport this to |
The remote debugging frame cache previously used only the last_profiled_frame address as its cache anchor. If a frame returned and a later frame reused the same _PyInterpreterFrame address, the profiler could accept a stale cache entry and splice parent frames from a different call chain into the current stack. This adds a last_profiled_frame_seq counter next to last_profiled_frame, increments it when the anchor advances, stores it in frame cache entries, and validates cache hits against both the frame address and the sequence. Cache miss walks now copy stack chunks before storing new cache entries so stored continuations come from a stable snapshot. The new regression test exercises alternating call chains and checks that cached stacks never contain frames from both branches. (cherry picked from commit 8cda6ae)
gh-151613: Fix remote debugging frame cache ABA (#151614) The remote debugging frame cache previously used only the last_profiled_frame address as its cache anchor. If a frame returned and a later frame reused the same _PyInterpreterFrame address, the profiler could accept a stale cache entry and splice parent frames from a different call chain into the current stack. This adds a last_profiled_frame_seq counter next to last_profiled_frame, increments it when the anchor advances, stores it in frame cache entries, and validates cache hits against both the frame address and the sequence. Cache miss walks now copy stack chunks before storing new cache entries so stored continuations come from a stable snapshot. The new regression test exercises alternating call chains and checks that cached stacks never contain frames from both branches. (cherry picked from commit 8cda6ae)
Fixes #151613.
The remote debugging frame cache previously used only the
last_profiled_frameaddress as its cache anchor. If a frame returned and a later frame reused the same_PyInterpreterFrameaddress, the profiler could accept a stale cache entry and splice parent frames from a different call chain into the current stack.This adds a
last_profiled_frame_seqcounter next tolast_profiled_frame, increments it when the anchor advances, stores it in frame cache entries, and validates cache hits against both the frame address and the sequence. Cache miss walks now copy stack chunks before storing new cache entries so stored continuations come from a stable snapshot. The new regression test exercises alternating call chains and checks that cached stacks never contain frames from both branches.