Skip to content

Commit

Permalink
bpo-40429: PyThreadState_GetFrame() returns a strong ref (GH-19781)
Browse files Browse the repository at this point in the history
The PyThreadState_GetFrame() function now returns a strong reference
to the frame.
  • Loading branch information
vstinner committed Apr 29, 2020
1 parent 37af21b commit 4386b90
Show file tree
Hide file tree
Showing 7 changed files with 26 additions and 20 deletions.
6 changes: 3 additions & 3 deletions Doc/c-api/init.rst
Expand Up @@ -1074,10 +1074,10 @@ All of the following functions must be called after :c:func:`Py_Initialize`.
.. c:function:: PyFrameObject* PyThreadState_GetFrame(PyThreadState *tstate)
Get a borrowed reference to the current frame of the Python thread state
*tstate*.
Get the current frame of the Python thread state *tstate*.
Return ``NULL`` if no frame is currently executing.
Return a strong reference. Return ``NULL`` if no frame is currently
executing.
See also :c:func:`PyEval_GetFrame`.
Expand Down
@@ -0,0 +1,2 @@
The :c:func:`PyThreadState_GetFrame` function now returns a strong reference
to the frame.
8 changes: 3 additions & 5 deletions Modules/_tracemalloc.c
Expand Up @@ -425,18 +425,16 @@ traceback_hash(traceback_t *traceback)
static void
traceback_get_frames(traceback_t *traceback)
{
PyThreadState *tstate;
PyFrameObject *pyframe;

tstate = PyGILState_GetThisThreadState();
PyThreadState *tstate = PyGILState_GetThisThreadState();
if (tstate == NULL) {
#ifdef TRACE_DEBUG
tracemalloc_error("failed to get the current thread state");
#endif
return;
}

pyframe = PyThreadState_GetFrame(tstate);
PyFrameObject *pyframe = PyThreadState_GetFrame(tstate);
Py_XDECREF(pyframe); // use a borrowed reference
for (; pyframe != NULL; pyframe = pyframe->f_back) {
if (traceback->nframe < _Py_tracemalloc_config.max_nframe) {
tracemalloc_get_frame(pyframe, &traceback->frames[traceback->nframe]);
Expand Down
11 changes: 7 additions & 4 deletions Modules/_xxsubinterpretersmodule.c
Expand Up @@ -1840,14 +1840,17 @@ _is_running(PyInterpreterState *interp)
"interpreter has more than one thread");
return -1;
}

assert(!PyErr_Occurred());
PyFrameObject *frame = PyThreadState_GetFrame(tstate);
if (frame == NULL) {
if (PyErr_Occurred() != NULL) {
return -1;
}
return 0;
}
return (int)(frame->f_executing);

int executing = (int)(frame->f_executing);
Py_DECREF(frame);

return executing;
}

static int
Expand Down
9 changes: 5 additions & 4 deletions Objects/typeobject.c
Expand Up @@ -8108,15 +8108,16 @@ super_init(PyObject *self, PyObject *args, PyObject *kwds)
/* Call super(), without args -- fill in from __class__
and first local variable on the stack. */
PyThreadState *tstate = _PyThreadState_GET();
PyFrameObject *f = PyThreadState_GetFrame(tstate);
if (f == NULL) {
PyFrameObject *frame = PyThreadState_GetFrame(tstate);
if (frame == NULL) {
PyErr_SetString(PyExc_RuntimeError,
"super(): no current frame");
return -1;
}

PyCodeObject *code = PyFrame_GetCode(f);
int res = super_init_without_args(f, code, &type, &obj);
PyCodeObject *code = PyFrame_GetCode(frame);
int res = super_init_without_args(frame, code, &type, &obj);
Py_DECREF(frame);
Py_DECREF(code);

if (res < 0) {
Expand Down
2 changes: 1 addition & 1 deletion Python/errors.c
Expand Up @@ -1372,7 +1372,7 @@ _PyErr_WriteUnraisableMsg(const char *err_msg_str, PyObject *obj)
}

if (exc_tb == NULL) {
struct _frame *frame = tstate->frame;
PyFrameObject *frame = tstate->frame;
if (frame != NULL) {
exc_tb = _PyTraceBack_FromFrame(NULL, frame);
if (exc_tb == NULL) {
Expand Down
8 changes: 5 additions & 3 deletions Python/pystate.c
Expand Up @@ -1042,11 +1042,13 @@ PyThreadState_GetInterpreter(PyThreadState *tstate)
}


struct _frame*
PyFrameObject*
PyThreadState_GetFrame(PyThreadState *tstate)
{
assert(tstate != NULL);
return tstate->frame;
PyFrameObject *frame = tstate->frame;
Py_XINCREF(frame);
return frame;
}


Expand Down Expand Up @@ -1165,7 +1167,7 @@ _PyThread_CurrentFrames(void)
for (i = runtime->interpreters.head; i != NULL; i = i->next) {
PyThreadState *t;
for (t = i->tstate_head; t != NULL; t = t->next) {
struct _frame *frame = t->frame;
PyFrameObject *frame = t->frame;
if (frame == NULL) {
continue;
}
Expand Down

0 comments on commit 4386b90

Please sign in to comment.