bpo-40429: PyThreadState_GetFrame() returns a strong ref (GH-19781)

The PyThreadState_GetFrame() function now returns a strong reference
to the frame.
This commit is contained in:
Victor Stinner 2020-04-29 03:01:43 +02:00 committed by GitHub
parent 37af21b667
commit 4386b9045e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 26 additions and 20 deletions

View File

@ -1074,10 +1074,10 @@ All of the following functions must be called after :c:func:`Py_Initialize`.
.. c:function:: PyFrameObject* PyThreadState_GetFrame(PyThreadState *tstate) .. c:function:: PyFrameObject* PyThreadState_GetFrame(PyThreadState *tstate)
Get a borrowed reference to the current frame of the Python thread state Get the current frame of the Python thread state *tstate*.
*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`. See also :c:func:`PyEval_GetFrame`.

View File

@ -0,0 +1,2 @@
The :c:func:`PyThreadState_GetFrame` function now returns a strong reference
to the frame.

View File

@ -425,10 +425,7 @@ traceback_hash(traceback_t *traceback)
static void static void
traceback_get_frames(traceback_t *traceback) traceback_get_frames(traceback_t *traceback)
{ {
PyThreadState *tstate; PyThreadState *tstate = PyGILState_GetThisThreadState();
PyFrameObject *pyframe;
tstate = PyGILState_GetThisThreadState();
if (tstate == NULL) { if (tstate == NULL) {
#ifdef TRACE_DEBUG #ifdef TRACE_DEBUG
tracemalloc_error("failed to get the current thread state"); tracemalloc_error("failed to get the current thread state");
@ -436,7 +433,8 @@ traceback_get_frames(traceback_t *traceback)
return; return;
} }
pyframe = PyThreadState_GetFrame(tstate); PyFrameObject *pyframe = PyThreadState_GetFrame(tstate);
Py_XDECREF(pyframe); // use a borrowed reference
for (; pyframe != NULL; pyframe = pyframe->f_back) { for (; pyframe != NULL; pyframe = pyframe->f_back) {
if (traceback->nframe < _Py_tracemalloc_config.max_nframe) { if (traceback->nframe < _Py_tracemalloc_config.max_nframe) {
tracemalloc_get_frame(pyframe, &traceback->frames[traceback->nframe]); tracemalloc_get_frame(pyframe, &traceback->frames[traceback->nframe]);

View File

@ -1840,14 +1840,17 @@ _is_running(PyInterpreterState *interp)
"interpreter has more than one thread"); "interpreter has more than one thread");
return -1; return -1;
} }
assert(!PyErr_Occurred());
PyFrameObject *frame = PyThreadState_GetFrame(tstate); PyFrameObject *frame = PyThreadState_GetFrame(tstate);
if (frame == NULL) { if (frame == NULL) {
if (PyErr_Occurred() != NULL) {
return -1;
}
return 0; return 0;
} }
return (int)(frame->f_executing);
int executing = (int)(frame->f_executing);
Py_DECREF(frame);
return executing;
} }
static int static int

View File

@ -8108,15 +8108,16 @@ super_init(PyObject *self, PyObject *args, PyObject *kwds)
/* Call super(), without args -- fill in from __class__ /* Call super(), without args -- fill in from __class__
and first local variable on the stack. */ and first local variable on the stack. */
PyThreadState *tstate = _PyThreadState_GET(); PyThreadState *tstate = _PyThreadState_GET();
PyFrameObject *f = PyThreadState_GetFrame(tstate); PyFrameObject *frame = PyThreadState_GetFrame(tstate);
if (f == NULL) { if (frame == NULL) {
PyErr_SetString(PyExc_RuntimeError, PyErr_SetString(PyExc_RuntimeError,
"super(): no current frame"); "super(): no current frame");
return -1; return -1;
} }
PyCodeObject *code = PyFrame_GetCode(f); PyCodeObject *code = PyFrame_GetCode(frame);
int res = super_init_without_args(f, code, &type, &obj); int res = super_init_without_args(frame, code, &type, &obj);
Py_DECREF(frame);
Py_DECREF(code); Py_DECREF(code);
if (res < 0) { if (res < 0) {

View File

@ -1372,7 +1372,7 @@ _PyErr_WriteUnraisableMsg(const char *err_msg_str, PyObject *obj)
} }
if (exc_tb == NULL) { if (exc_tb == NULL) {
struct _frame *frame = tstate->frame; PyFrameObject *frame = tstate->frame;
if (frame != NULL) { if (frame != NULL) {
exc_tb = _PyTraceBack_FromFrame(NULL, frame); exc_tb = _PyTraceBack_FromFrame(NULL, frame);
if (exc_tb == NULL) { if (exc_tb == NULL) {

View File

@ -1042,11 +1042,13 @@ PyThreadState_GetInterpreter(PyThreadState *tstate)
} }
struct _frame* PyFrameObject*
PyThreadState_GetFrame(PyThreadState *tstate) PyThreadState_GetFrame(PyThreadState *tstate)
{ {
assert(tstate != NULL); 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) { for (i = runtime->interpreters.head; i != NULL; i = i->next) {
PyThreadState *t; PyThreadState *t;
for (t = i->tstate_head; t != NULL; t = t->next) { for (t = i->tstate_head; t != NULL; t = t->next) {
struct _frame *frame = t->frame; PyFrameObject *frame = t->frame;
if (frame == NULL) { if (frame == NULL) {
continue; continue;
} }