bpo-40429: PyFrame_GetCode() now returns a strong reference (GH-19773)

This commit is contained in:
Victor Stinner 2020-04-29 01:28:13 +02:00 committed by GitHub
parent 5e8c691594
commit 8852ad4208
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 35 additions and 26 deletions

View File

@ -33,10 +33,11 @@ Reflection
.. c:function:: int PyFrame_GetCode(PyFrameObject *frame) .. c:function:: int PyFrame_GetCode(PyFrameObject *frame)
Return a borrowed reference to the *frame* code. Get the *frame* code.
The frame code cannot be ``NULL``.
*frame* must not be ``NULL``. Return a strong reference.
*frame* must not be ``NULL``. The result (frame code) cannot be ``NULL``.
.. versionadded:: 3.9 .. versionadded:: 3.9

View File

@ -537,8 +537,7 @@ Optimizations
Build and C API Changes Build and C API Changes
======================= =======================
* New :c:func:`PyFrame_GetCode` function: return a borrowed reference to the * New :c:func:`PyFrame_GetCode` function: get a frame code.
frame code.
(Contributed by Victor Stinner in :issue:`40421`.) (Contributed by Victor Stinner in :issue:`40421`.)
* Add :c:func:`PyFrame_GetLineNumber` to the limited C API. * Add :c:func:`PyFrame_GetLineNumber` to the limited C API.

View File

@ -390,14 +390,19 @@ profiler_callback(PyObject *self, PyFrameObject *frame, int what,
{ {
PyCodeObject *code = PyFrame_GetCode(frame); PyCodeObject *code = PyFrame_GetCode(frame);
ptrace_enter_call(self, (void *)code, (PyObject *)code); ptrace_enter_call(self, (void *)code, (PyObject *)code);
Py_DECREF(code);
break; break;
} }
/* the 'frame' of a called function is about to finish /* the 'frame' of a called function is about to finish
(either normally or with an exception) */ (either normally or with an exception) */
case PyTrace_RETURN: case PyTrace_RETURN:
ptrace_leave_call(self, (void *)PyFrame_GetCode(frame)); {
PyCodeObject *code = PyFrame_GetCode(frame);
ptrace_leave_call(self, (void *)code);
Py_DECREF(code);
break; break;
}
/* case PyTrace_EXCEPTION: /* case PyTrace_EXCEPTION:
If the exception results in the function exiting, a If the exception results in the function exiting, a

View File

@ -335,26 +335,24 @@ hashtable_compare_traceback(_Py_hashtable_t *ht, const void *pkey,
static void static void
tracemalloc_get_frame(PyFrameObject *pyframe, frame_t *frame) tracemalloc_get_frame(PyFrameObject *pyframe, frame_t *frame)
{ {
PyCodeObject *code;
PyObject *filename;
_Py_hashtable_entry_t *entry;
int lineno;
frame->filename = unknown_filename; frame->filename = unknown_filename;
lineno = PyFrame_GetLineNumber(pyframe); int lineno = PyFrame_GetLineNumber(pyframe);
if (lineno < 0) if (lineno < 0) {
lineno = 0; lineno = 0;
}
frame->lineno = (unsigned int)lineno; frame->lineno = (unsigned int)lineno;
code = PyFrame_GetCode(pyframe); PyCodeObject *code = PyFrame_GetCode(pyframe);
if (code->co_filename == NULL) { PyObject *filename = code->co_filename;
Py_DECREF(code);
if (filename == NULL) {
#ifdef TRACE_DEBUG #ifdef TRACE_DEBUG
tracemalloc_error("failed to get the filename of the code object"); tracemalloc_error("failed to get the filename of the code object");
#endif #endif
return; return;
} }
filename = code->co_filename;
assert(filename != NULL); assert(filename != NULL);
if (filename == NULL) if (filename == NULL)
return; return;
@ -375,6 +373,7 @@ tracemalloc_get_frame(PyFrameObject *pyframe, frame_t *frame)
} }
/* intern the filename */ /* intern the filename */
_Py_hashtable_entry_t *entry;
entry = _Py_HASHTABLE_GET_ENTRY(tracemalloc_filenames, filename); entry = _Py_HASHTABLE_GET_ENTRY(tracemalloc_filenames, filename);
if (entry != NULL) { if (entry != NULL) {
_Py_HASHTABLE_ENTRY_READ_KEY(tracemalloc_filenames, entry, filename); _Py_HASHTABLE_ENTRY_READ_KEY(tracemalloc_filenames, entry, filename);

View File

@ -1237,5 +1237,6 @@ PyFrame_GetCode(PyFrameObject *frame)
assert(frame != NULL); assert(frame != NULL);
PyCodeObject *code = frame->f_code; PyCodeObject *code = frame->f_code;
assert(code != NULL); assert(code != NULL);
Py_INCREF(code);
return code; return code;
} }

View File

@ -8031,7 +8031,6 @@ 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. */
PyFrameObject *f; PyFrameObject *f;
PyCodeObject *co;
Py_ssize_t i, n; Py_ssize_t i, n;
f = PyThreadState_GetFrame(_PyThreadState_GET()); f = PyThreadState_GetFrame(_PyThreadState_GET());
if (f == NULL) { if (f == NULL) {
@ -8039,7 +8038,8 @@ super_init(PyObject *self, PyObject *args, PyObject *kwds)
"super(): no current frame"); "super(): no current frame");
return -1; return -1;
} }
co = PyFrame_GetCode(f); PyCodeObject *co = PyFrame_GetCode(f);
Py_DECREF(co); // use a borrowed reference
if (co->co_argcount == 0) { if (co->co_argcount == 0) {
PyErr_SetString(PyExc_RuntimeError, PyErr_SetString(PyExc_RuntimeError,
"super(): no arguments"); "super(): no arguments");

View File

@ -785,6 +785,8 @@ is_internal_frame(PyFrameObject *frame)
PyCodeObject *code = PyFrame_GetCode(frame); PyCodeObject *code = PyFrame_GetCode(frame);
PyObject *filename = code->co_filename; PyObject *filename = code->co_filename;
Py_DECREF(code);
if (filename == NULL) { if (filename == NULL) {
return 0; return 0;
} }
@ -850,7 +852,9 @@ setup_context(Py_ssize_t stack_level, PyObject **filename, int *lineno,
} }
else { else {
globals = f->f_globals; globals = f->f_globals;
*filename = PyFrame_GetCode(f)->co_filename; PyCodeObject *code = PyFrame_GetCode(f);
*filename = code->co_filename;
Py_DECREF(code);
Py_INCREF(*filename); Py_INCREF(*filename);
*lineno = PyFrame_GetLineNumber(f); *lineno = PyFrame_GetLineNumber(f);
} }

View File

@ -1557,6 +1557,7 @@ remove_importlib_frames(PyThreadState *tstate)
else { else {
prev_link = (PyObject **) &traceback->tb_next; prev_link = (PyObject **) &traceback->tb_next;
} }
Py_DECREF(code);
tb = next; tb = next;
} }
done: done:

View File

@ -581,6 +581,7 @@ tb_printinternal(PyTracebackObject *tb, PyObject *f, long limit)
err = PyErr_CheckSignals(); err = PyErr_CheckSignals();
} }
} }
Py_DECREF(code);
tb = tb->tb_next; tb = tb->tb_next;
} }
if (err == 0 && cnt > TB_RECURSIVE_CUTOFF) { if (err == 0 && cnt > TB_RECURSIVE_CUTOFF) {
@ -752,12 +753,9 @@ _Py_DumpASCII(int fd, PyObject *text)
static void static void
dump_frame(int fd, PyFrameObject *frame) dump_frame(int fd, PyFrameObject *frame)
{ {
PyCodeObject *code; PyCodeObject *code = PyFrame_GetCode(frame);
int lineno;
code = PyFrame_GetCode(frame);
PUTS(fd, " File "); PUTS(fd, " File ");
if (code != NULL && code->co_filename != NULL if (code->co_filename != NULL
&& PyUnicode_Check(code->co_filename)) && PyUnicode_Check(code->co_filename))
{ {
PUTS(fd, "\""); PUTS(fd, "\"");
@ -768,7 +766,7 @@ dump_frame(int fd, PyFrameObject *frame)
} }
/* PyFrame_GetLineNumber() was introduced in Python 2.7.0 and 3.2.0 */ /* PyFrame_GetLineNumber() was introduced in Python 2.7.0 and 3.2.0 */
lineno = PyCode_Addr2Line(code, frame->f_lasti); int lineno = PyCode_Addr2Line(code, frame->f_lasti);
PUTS(fd, ", line "); PUTS(fd, ", line ");
if (lineno >= 0) { if (lineno >= 0) {
_Py_DumpDecimal(fd, (unsigned long)lineno); _Py_DumpDecimal(fd, (unsigned long)lineno);
@ -778,7 +776,7 @@ dump_frame(int fd, PyFrameObject *frame)
} }
PUTS(fd, " in "); PUTS(fd, " in ");
if (code != NULL && code->co_name != NULL if (code->co_name != NULL
&& PyUnicode_Check(code->co_name)) { && PyUnicode_Check(code->co_name)) {
_Py_DumpASCII(fd, code->co_name); _Py_DumpASCII(fd, code->co_name);
} }
@ -787,6 +785,7 @@ dump_frame(int fd, PyFrameObject *frame)
} }
PUTS(fd, "\n"); PUTS(fd, "\n");
Py_DECREF(code);
} }
static void static void