Skip to content

Commit 4386b90

Browse files
authored
bpo-40429: PyThreadState_GetFrame() returns a strong ref (pythonGH-19781)
The PyThreadState_GetFrame() function now returns a strong reference to the frame.
1 parent 37af21b commit 4386b90

File tree

7 files changed

+26
-20
lines changed

7 files changed

+26
-20
lines changed

Doc/c-api/init.rst

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1074,10 +1074,10 @@ All of the following functions must be called after :c:func:`Py_Initialize`.
10741074
10751075
.. c:function:: PyFrameObject* PyThreadState_GetFrame(PyThreadState *tstate)
10761076
1077-
Get a borrowed reference to the current frame of the Python thread state
1078-
*tstate*.
1077+
Get the current frame of the Python thread state *tstate*.
10791078
1080-
Return ``NULL`` if no frame is currently executing.
1079+
Return a strong reference. Return ``NULL`` if no frame is currently
1080+
executing.
10811081
10821082
See also :c:func:`PyEval_GetFrame`.
10831083
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
The :c:func:`PyThreadState_GetFrame` function now returns a strong reference
2+
to the frame.

Modules/_tracemalloc.c

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -425,18 +425,16 @@ traceback_hash(traceback_t *traceback)
425425
static void
426426
traceback_get_frames(traceback_t *traceback)
427427
{
428-
PyThreadState *tstate;
429-
PyFrameObject *pyframe;
430-
431-
tstate = PyGILState_GetThisThreadState();
428+
PyThreadState *tstate = PyGILState_GetThisThreadState();
432429
if (tstate == NULL) {
433430
#ifdef TRACE_DEBUG
434431
tracemalloc_error("failed to get the current thread state");
435432
#endif
436433
return;
437434
}
438435

439-
pyframe = PyThreadState_GetFrame(tstate);
436+
PyFrameObject *pyframe = PyThreadState_GetFrame(tstate);
437+
Py_XDECREF(pyframe); // use a borrowed reference
440438
for (; pyframe != NULL; pyframe = pyframe->f_back) {
441439
if (traceback->nframe < _Py_tracemalloc_config.max_nframe) {
442440
tracemalloc_get_frame(pyframe, &traceback->frames[traceback->nframe]);

Modules/_xxsubinterpretersmodule.c

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1840,14 +1840,17 @@ _is_running(PyInterpreterState *interp)
18401840
"interpreter has more than one thread");
18411841
return -1;
18421842
}
1843+
1844+
assert(!PyErr_Occurred());
18431845
PyFrameObject *frame = PyThreadState_GetFrame(tstate);
18441846
if (frame == NULL) {
1845-
if (PyErr_Occurred() != NULL) {
1846-
return -1;
1847-
}
18481847
return 0;
18491848
}
1850-
return (int)(frame->f_executing);
1849+
1850+
int executing = (int)(frame->f_executing);
1851+
Py_DECREF(frame);
1852+
1853+
return executing;
18511854
}
18521855

18531856
static int

Objects/typeobject.c

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8108,15 +8108,16 @@ super_init(PyObject *self, PyObject *args, PyObject *kwds)
81088108
/* Call super(), without args -- fill in from __class__
81098109
and first local variable on the stack. */
81108110
PyThreadState *tstate = _PyThreadState_GET();
8111-
PyFrameObject *f = PyThreadState_GetFrame(tstate);
8112-
if (f == NULL) {
8111+
PyFrameObject *frame = PyThreadState_GetFrame(tstate);
8112+
if (frame == NULL) {
81138113
PyErr_SetString(PyExc_RuntimeError,
81148114
"super(): no current frame");
81158115
return -1;
81168116
}
81178117

8118-
PyCodeObject *code = PyFrame_GetCode(f);
8119-
int res = super_init_without_args(f, code, &type, &obj);
8118+
PyCodeObject *code = PyFrame_GetCode(frame);
8119+
int res = super_init_without_args(frame, code, &type, &obj);
8120+
Py_DECREF(frame);
81208121
Py_DECREF(code);
81218122

81228123
if (res < 0) {

Python/errors.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1372,7 +1372,7 @@ _PyErr_WriteUnraisableMsg(const char *err_msg_str, PyObject *obj)
13721372
}
13731373

13741374
if (exc_tb == NULL) {
1375-
struct _frame *frame = tstate->frame;
1375+
PyFrameObject *frame = tstate->frame;
13761376
if (frame != NULL) {
13771377
exc_tb = _PyTraceBack_FromFrame(NULL, frame);
13781378
if (exc_tb == NULL) {

Python/pystate.c

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1042,11 +1042,13 @@ PyThreadState_GetInterpreter(PyThreadState *tstate)
10421042
}
10431043

10441044

1045-
struct _frame*
1045+
PyFrameObject*
10461046
PyThreadState_GetFrame(PyThreadState *tstate)
10471047
{
10481048
assert(tstate != NULL);
1049-
return tstate->frame;
1049+
PyFrameObject *frame = tstate->frame;
1050+
Py_XINCREF(frame);
1051+
return frame;
10501052
}
10511053

10521054

@@ -1165,7 +1167,7 @@ _PyThread_CurrentFrames(void)
11651167
for (i = runtime->interpreters.head; i != NULL; i = i->next) {
11661168
PyThreadState *t;
11671169
for (t = i->tstate_head; t != NULL; t = t->next) {
1168-
struct _frame *frame = t->frame;
1170+
PyFrameObject *frame = t->frame;
11691171
if (frame == NULL) {
11701172
continue;
11711173
}

0 commit comments

Comments
 (0)