From 4386b9045e5fe1151e65c2816264b5710000eb9f Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Wed, 29 Apr 2020 03:01:43 +0200 Subject: bpo-40429: PyThreadState_GetFrame() returns a strong ref (GH-19781) The PyThreadState_GetFrame() function now returns a strong reference to the frame. --- Doc/c-api/init.rst | 6 +++--- .../next/C API/2020-04-29-01-39-41.bpo-40429.VQfvta.rst | 2 ++ Modules/_tracemalloc.c | 8 +++----- Modules/_xxsubinterpretersmodule.c | 11 +++++++---- Objects/typeobject.c | 9 +++++---- Python/errors.c | 2 +- Python/pystate.c | 8 +++++--- 7 files changed, 26 insertions(+), 20 deletions(-) create mode 100644 Misc/NEWS.d/next/C API/2020-04-29-01-39-41.bpo-40429.VQfvta.rst diff --git a/Doc/c-api/init.rst b/Doc/c-api/init.rst index afde3db..68fed2a 100644 --- a/Doc/c-api/init.rst +++ b/Doc/c-api/init.rst @@ -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`. diff --git a/Misc/NEWS.d/next/C API/2020-04-29-01-39-41.bpo-40429.VQfvta.rst b/Misc/NEWS.d/next/C API/2020-04-29-01-39-41.bpo-40429.VQfvta.rst new file mode 100644 index 0000000..e02aaf9 --- /dev/null +++ b/Misc/NEWS.d/next/C API/2020-04-29-01-39-41.bpo-40429.VQfvta.rst @@ -0,0 +1,2 @@ +The :c:func:`PyThreadState_GetFrame` function now returns a strong reference +to the frame. diff --git a/Modules/_tracemalloc.c b/Modules/_tracemalloc.c index 24628a9..6f28f7f 100644 --- a/Modules/_tracemalloc.c +++ b/Modules/_tracemalloc.c @@ -425,10 +425,7 @@ 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"); @@ -436,7 +433,8 @@ traceback_get_frames(traceback_t *traceback) 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]); diff --git a/Modules/_xxsubinterpretersmodule.c b/Modules/_xxsubinterpretersmodule.c index e618930..15e8055 100644 --- a/Modules/_xxsubinterpretersmodule.c +++ b/Modules/_xxsubinterpretersmodule.c @@ -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 diff --git a/Objects/typeobject.c b/Objects/typeobject.c index 7ba51e3..c2ddc16 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -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) { diff --git a/Python/errors.c b/Python/errors.c index db00770..9e53d05 100644 --- a/Python/errors.c +++ b/Python/errors.c @@ -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) { diff --git a/Python/pystate.c b/Python/pystate.c index d6f5882..dd95750 100644 --- a/Python/pystate.c +++ b/Python/pystate.c @@ -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; } @@ -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; } -- cgit v0.12