]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
bpo-40429: PyFrame_GetCode() now returns a strong reference (GH-19773)
authorVictor Stinner <vstinner@python.org>
Tue, 28 Apr 2020 23:28:13 +0000 (01:28 +0200)
committerGitHub <noreply@github.com>
Tue, 28 Apr 2020 23:28:13 +0000 (01:28 +0200)
Doc/c-api/reflection.rst
Doc/whatsnew/3.9.rst
Modules/_lsprof.c
Modules/_tracemalloc.c
Objects/frameobject.c
Objects/typeobject.c
Python/_warnings.c
Python/import.c
Python/traceback.c

index 594c1ec7943f750d9fcc5e71ccd32123fa526b83..21d9878609127182368139203bfd7bd779dd7aa1 100644 (file)
@@ -33,10 +33,11 @@ Reflection
 
 .. c:function:: int PyFrame_GetCode(PyFrameObject *frame)
 
-   Return a borrowed reference to the *frame* code.
-   The frame code cannot be ``NULL``.
+   Get the *frame* code.
 
-   *frame* must not be ``NULL``.
+   Return a strong reference.
+
+   *frame* must not be ``NULL``. The result (frame code) cannot be ``NULL``.
 
    .. versionadded:: 3.9
 
index e3751fa1680117bba490ca0738a34f3e1231e77c..cb3afd593571a9536696e48a9bb6ba8022b03020 100644 (file)
@@ -537,8 +537,7 @@ Optimizations
 Build and C API Changes
 =======================
 
-* New :c:func:`PyFrame_GetCode` function: return a borrowed reference to the
-  frame code.
+* New :c:func:`PyFrame_GetCode` function: get a frame code.
   (Contributed by Victor Stinner in :issue:`40421`.)
 
 * Add :c:func:`PyFrame_GetLineNumber` to the limited C API.
index 39cf6e126d635f7a3e6caa63f9105b27dcffb750..5e53d839640d994f01e15309a698f98dc2b1193e 100644 (file)
@@ -390,14 +390,19 @@ profiler_callback(PyObject *self, PyFrameObject *frame, int what,
     {
         PyCodeObject *code = PyFrame_GetCode(frame);
         ptrace_enter_call(self, (void *)code, (PyObject *)code);
+        Py_DECREF(code);
         break;
     }
 
     /* the 'frame' of a called function is about to finish
        (either normally or with an exception) */
     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;
+    }
 
     /* case PyTrace_EXCEPTION:
         If the exception results in the function exiting, a
index b2a000302164e38140d71982cdc353b33c25b593..24628a907f28ace87558d7404de713113ec0e79b 100644 (file)
@@ -335,26 +335,24 @@ hashtable_compare_traceback(_Py_hashtable_t *ht, const void *pkey,
 static void
 tracemalloc_get_frame(PyFrameObject *pyframe, frame_t *frame)
 {
-    PyCodeObject *code;
-    PyObject *filename;
-    _Py_hashtable_entry_t *entry;
-    int lineno;
-
     frame->filename = unknown_filename;
-    lineno = PyFrame_GetLineNumber(pyframe);
-    if (lineno < 0)
+    int lineno = PyFrame_GetLineNumber(pyframe);
+    if (lineno < 0) {
         lineno = 0;
+    }
     frame->lineno = (unsigned int)lineno;
 
-    code = PyFrame_GetCode(pyframe);
-    if (code->co_filename == NULL) {
+    PyCodeObject *code = PyFrame_GetCode(pyframe);
+    PyObject *filename = code->co_filename;
+    Py_DECREF(code);
+
+    if (filename == NULL) {
 #ifdef TRACE_DEBUG
         tracemalloc_error("failed to get the filename of the code object");
 #endif
         return;
     }
 
-    filename = code->co_filename;
     assert(filename != NULL);
     if (filename == NULL)
         return;
@@ -375,6 +373,7 @@ tracemalloc_get_frame(PyFrameObject *pyframe, frame_t *frame)
     }
 
     /* intern the filename */
+    _Py_hashtable_entry_t *entry;
     entry = _Py_HASHTABLE_GET_ENTRY(tracemalloc_filenames, filename);
     if (entry != NULL) {
         _Py_HASHTABLE_ENTRY_READ_KEY(tracemalloc_filenames, entry, filename);
index 6b3559ee9625efb2b0e31553680327b669b3c2a1..533186bc046f0f748053c0da7f413a25f5dcfe4d 100644 (file)
@@ -1237,5 +1237,6 @@ PyFrame_GetCode(PyFrameObject *frame)
     assert(frame != NULL);
     PyCodeObject *code = frame->f_code;
     assert(code != NULL);
+    Py_INCREF(code);
     return code;
 }
index f65f05386cbe7a98e8cea816a76f7ba285c8062f..8f9ab5c0bae621c850932ca591fe0f1701b05cae 100644 (file)
@@ -8031,7 +8031,6 @@ super_init(PyObject *self, PyObject *args, PyObject *kwds)
         /* Call super(), without args -- fill in from __class__
            and first local variable on the stack. */
         PyFrameObject *f;
-        PyCodeObject *co;
         Py_ssize_t i, n;
         f = PyThreadState_GetFrame(_PyThreadState_GET());
         if (f == NULL) {
@@ -8039,7 +8038,8 @@ super_init(PyObject *self, PyObject *args, PyObject *kwds)
                             "super(): no current frame");
             return -1;
         }
-        co = PyFrame_GetCode(f);
+        PyCodeObject *co = PyFrame_GetCode(f);
+        Py_DECREF(co);   // use a borrowed reference
         if (co->co_argcount == 0) {
             PyErr_SetString(PyExc_RuntimeError,
                             "super(): no arguments");
index 7a620dc54310c9c81be44d55eb155795b66a75cb..7c15ce0ef89c347908835ec64f7fb5e5429655e8 100644 (file)
@@ -785,6 +785,8 @@ is_internal_frame(PyFrameObject *frame)
 
     PyCodeObject *code = PyFrame_GetCode(frame);
     PyObject *filename = code->co_filename;
+    Py_DECREF(code);
+
     if (filename == NULL) {
         return 0;
     }
@@ -850,7 +852,9 @@ setup_context(Py_ssize_t stack_level, PyObject **filename, int *lineno,
     }
     else {
         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);
         *lineno = PyFrame_GetLineNumber(f);
     }
index 9142ebba40dfe40f5382a981a0f89e656b5d9c5b..8c94e0ec54655a3c34a2d06457239caaa16ecad5 100644 (file)
@@ -1557,6 +1557,7 @@ remove_importlib_frames(PyThreadState *tstate)
         else {
             prev_link = (PyObject **) &traceback->tb_next;
         }
+        Py_DECREF(code);
         tb = next;
     }
 done:
index 1ea6cbada964f5320ba54e5739ea253fbc9a227f..438a2c4fce7ca7edb08f300956104682dcb6f5de 100644 (file)
@@ -581,6 +581,7 @@ tb_printinternal(PyTracebackObject *tb, PyObject *f, long limit)
                 err = PyErr_CheckSignals();
             }
         }
+        Py_DECREF(code);
         tb = tb->tb_next;
     }
     if (err == 0 && cnt > TB_RECURSIVE_CUTOFF) {
@@ -752,12 +753,9 @@ _Py_DumpASCII(int fd, PyObject *text)
 static void
 dump_frame(int fd, PyFrameObject *frame)
 {
-    PyCodeObject *code;
-    int lineno;
-
-    code = PyFrame_GetCode(frame);
+    PyCodeObject *code = PyFrame_GetCode(frame);
     PUTS(fd, "  File ");
-    if (code != NULL && code->co_filename != NULL
+    if (code->co_filename != NULL
         && PyUnicode_Check(code->co_filename))
     {
         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 */
-    lineno = PyCode_Addr2Line(code, frame->f_lasti);
+    int lineno = PyCode_Addr2Line(code, frame->f_lasti);
     PUTS(fd, ", line ");
     if (lineno >= 0) {
         _Py_DumpDecimal(fd, (unsigned long)lineno);
@@ -778,7 +776,7 @@ dump_frame(int fd, PyFrameObject *frame)
     }
     PUTS(fd, " in ");
 
-    if (code != NULL && code->co_name != NULL
+    if (code->co_name != NULL
        && PyUnicode_Check(code->co_name)) {
         _Py_DumpASCII(fd, code->co_name);
     }
@@ -787,6 +785,7 @@ dump_frame(int fd, PyFrameObject *frame)
     }
 
     PUTS(fd, "\n");
+    Py_DECREF(code);
 }
 
 static void