Skip to content

Commit 2cf3c98

Browse files
committed
Add more comments strssing the importance satck discipline when dealing with CFrames.
1 parent 6458071 commit 2cf3c98

File tree

2 files changed

+18
-3
lines changed

2 files changed

+18
-3
lines changed

Include/cpython/pystate.h

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,15 @@ typedef int (*Py_tracefunc)(PyObject *, PyFrameObject *, int, PyObject *);
3131

3232
typedef struct _cframe {
3333
/* This struct will be threaded through the C stack
34-
* allowing faster access to state that must can be modified
35-
* outside of the interpreter must be accessed within it */
34+
* allowing fast access to per-thread state that needs
35+
* to be accessed quickly by the interpreter, but can
36+
* be modified outside of the interpreter.
37+
*
38+
* WARNING: This makes data on the C stack accessible from
39+
* heap objects. Care must be taken to maintain stack
40+
* discipline and make sure that instances of this struct cannot
41+
* accessed outside of their lifetime.
42+
*/
3643
int use_tracing;
3744
struct _cframe *previous;
3845
} CFrame;
@@ -69,6 +76,9 @@ struct _ts {
6976
This is to prevent the actual trace/profile code from being recorded in
7077
the trace/profile. */
7178
int tracing;
79+
80+
/* Pointer to current CFrame in the C stack frame of the currently,
81+
* or most recently, executing _PyEval_EvalFrameDefault. */
7282
CFrame *cframe;
7383

7484
Py_tracefunc c_profilefunc;
@@ -136,6 +146,7 @@ struct _ts {
136146

137147
/* Unique thread state id. */
138148
uint64_t id;
149+
139150
CFrame root_cframe;
140151

141152
/* XXX signal handlers should also be here */

Python/ceval.c

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1615,6 +1615,10 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, PyFrameObject *f, int throwflag)
16151615
/* Mark trace_info as uninitialized */
16161616
trace_info.code = NULL;
16171617

1618+
/* WARNING: Because the CFrame lives on the C stack,
1619+
* but can be accessed from a heap allocated object (tstate)
1620+
* strict stack discipline must be maintained.
1621+
*/
16181622
CFrame *prev_cframe = tstate->cframe;
16191623
trace_info.cframe.use_tracing = prev_cframe->use_tracing;
16201624
trace_info.cframe.previous = prev_cframe;
@@ -4588,7 +4592,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, PyFrameObject *f, int throwflag)
45884592

45894593
/* pop frame */
45904594
exit_eval_frame:
4591-
4595+
/* Restore previous cframe */
45924596
tstate->cframe = trace_info.cframe.previous;
45934597
tstate->cframe->use_tracing = trace_info.cframe.use_tracing;
45944598

0 commit comments

Comments
 (0)