@@ -111,6 +111,35 @@ The shim frame points to a special code object containing the `INTERPRETER_EXIT`
111111instruction which cleans up the shim frame and returns.
112112
113113
114+ ### Base frame
115+
116+ Each thread state contains an embedded ` _PyInterpreterFrame ` called the "base frame"
117+ that serves as a sentinel at the bottom of the frame stack. This frame is allocated
118+ in ` _PyThreadStateImpl ` (the internal extension of ` PyThreadState ` ) and initialized
119+ when the thread state is created. The ` owner ` field is set to ` FRAME_OWNED_BY_THREAD_STATE ` .
120+
121+ External profilers and sampling tools can validate that they have successfully unwound
122+ the complete call stack by checking that the frame chain terminates at the base frame.
123+ The ` PyThreadState.base_frame ` pointer provides the expected address to compare against.
124+ If a stack walk doesn't reach this frame, the sample is incomplete (possibly due to a
125+ race condition) and should be discarded.
126+
127+ The base frame is embedded in ` _PyThreadStateImpl ` rather than ` PyThreadState ` because
128+ ` _PyInterpreterFrame ` is defined in internal headers that cannot be exposed in the
129+ public API. A pointer (` PyThreadState.base_frame ` ) is provided for profilers to access
130+ the address without needing internal headers.
131+
132+ See the initialization in ` new_threadstate() ` in [ Python/pystate.c] ( ../Python/pystate.c ) .
133+
134+ #### How profilers should use the base frame
135+
136+ External profilers should read ` tstate->base_frame ` before walking the stack, then
137+ walk from ` tstate->current_frame ` following ` frame->previous ` pointers until reaching
138+ a frame with ` owner == FRAME_OWNED_BY_THREAD_STATE ` . After the walk, verify that the
139+ last frame address matches ` base_frame ` . If not, discard the sample as incomplete
140+ since the frame chain may have been in an inconsistent state due to concurrent updates.
141+
142+
114143### The Instruction Pointer
115144
116145` _PyInterpreterFrame ` has two fields which are used to maintain the instruction
0 commit comments