Skip to content

Commit 8852ad4

Browse files
authored
bpo-40429: PyFrame_GetCode() now returns a strong reference (GH-19773)
1 parent 5e8c691 commit 8852ad4

File tree

9 files changed

+35
-26
lines changed

9 files changed

+35
-26
lines changed

Doc/c-api/reflection.rst

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,10 +33,11 @@ Reflection
3333
3434
.. c:function:: int PyFrame_GetCode(PyFrameObject *frame)
3535
36-
Return a borrowed reference to the *frame* code.
37-
The frame code cannot be ``NULL``.
36+
Get the *frame* code.
3837
39-
*frame* must not be ``NULL``.
38+
Return a strong reference.
39+
40+
*frame* must not be ``NULL``. The result (frame code) cannot be ``NULL``.
4041
4142
.. versionadded:: 3.9
4243

Doc/whatsnew/3.9.rst

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -537,8 +537,7 @@ Optimizations
537537
Build and C API Changes
538538
=======================
539539

540-
* New :c:func:`PyFrame_GetCode` function: return a borrowed reference to the
541-
frame code.
540+
* New :c:func:`PyFrame_GetCode` function: get a frame code.
542541
(Contributed by Victor Stinner in :issue:`40421`.)
543542

544543
* Add :c:func:`PyFrame_GetLineNumber` to the limited C API.

Modules/_lsprof.c

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -390,14 +390,19 @@ profiler_callback(PyObject *self, PyFrameObject *frame, int what,
390390
{
391391
PyCodeObject *code = PyFrame_GetCode(frame);
392392
ptrace_enter_call(self, (void *)code, (PyObject *)code);
393+
Py_DECREF(code);
393394
break;
394395
}
395396

396397
/* the 'frame' of a called function is about to finish
397398
(either normally or with an exception) */
398399
case PyTrace_RETURN:
399-
ptrace_leave_call(self, (void *)PyFrame_GetCode(frame));
400+
{
401+
PyCodeObject *code = PyFrame_GetCode(frame);
402+
ptrace_leave_call(self, (void *)code);
403+
Py_DECREF(code);
400404
break;
405+
}
401406

402407
/* case PyTrace_EXCEPTION:
403408
If the exception results in the function exiting, a

Modules/_tracemalloc.c

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -335,26 +335,24 @@ hashtable_compare_traceback(_Py_hashtable_t *ht, const void *pkey,
335335
static void
336336
tracemalloc_get_frame(PyFrameObject *pyframe, frame_t *frame)
337337
{
338-
PyCodeObject *code;
339-
PyObject *filename;
340-
_Py_hashtable_entry_t *entry;
341-
int lineno;
342-
343338
frame->filename = unknown_filename;
344-
lineno = PyFrame_GetLineNumber(pyframe);
345-
if (lineno < 0)
339+
int lineno = PyFrame_GetLineNumber(pyframe);
340+
if (lineno < 0) {
346341
lineno = 0;
342+
}
347343
frame->lineno = (unsigned int)lineno;
348344

349-
code = PyFrame_GetCode(pyframe);
350-
if (code->co_filename == NULL) {
345+
PyCodeObject *code = PyFrame_GetCode(pyframe);
346+
PyObject *filename = code->co_filename;
347+
Py_DECREF(code);
348+
349+
if (filename == NULL) {
351350
#ifdef TRACE_DEBUG
352351
tracemalloc_error("failed to get the filename of the code object");
353352
#endif
354353
return;
355354
}
356355

357-
filename = code->co_filename;
358356
assert(filename != NULL);
359357
if (filename == NULL)
360358
return;
@@ -375,6 +373,7 @@ tracemalloc_get_frame(PyFrameObject *pyframe, frame_t *frame)
375373
}
376374

377375
/* intern the filename */
376+
_Py_hashtable_entry_t *entry;
378377
entry = _Py_HASHTABLE_GET_ENTRY(tracemalloc_filenames, filename);
379378
if (entry != NULL) {
380379
_Py_HASHTABLE_ENTRY_READ_KEY(tracemalloc_filenames, entry, filename);

Objects/frameobject.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1237,5 +1237,6 @@ PyFrame_GetCode(PyFrameObject *frame)
12371237
assert(frame != NULL);
12381238
PyCodeObject *code = frame->f_code;
12391239
assert(code != NULL);
1240+
Py_INCREF(code);
12401241
return code;
12411242
}

Objects/typeobject.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8031,15 +8031,15 @@ super_init(PyObject *self, PyObject *args, PyObject *kwds)
80318031
/* Call super(), without args -- fill in from __class__
80328032
and first local variable on the stack. */
80338033
PyFrameObject *f;
8034-
PyCodeObject *co;
80358034
Py_ssize_t i, n;
80368035
f = PyThreadState_GetFrame(_PyThreadState_GET());
80378036
if (f == NULL) {
80388037
PyErr_SetString(PyExc_RuntimeError,
80398038
"super(): no current frame");
80408039
return -1;
80418040
}
8042-
co = PyFrame_GetCode(f);
8041+
PyCodeObject *co = PyFrame_GetCode(f);
8042+
Py_DECREF(co); // use a borrowed reference
80438043
if (co->co_argcount == 0) {
80448044
PyErr_SetString(PyExc_RuntimeError,
80458045
"super(): no arguments");

Python/_warnings.c

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -785,6 +785,8 @@ is_internal_frame(PyFrameObject *frame)
785785

786786
PyCodeObject *code = PyFrame_GetCode(frame);
787787
PyObject *filename = code->co_filename;
788+
Py_DECREF(code);
789+
788790
if (filename == NULL) {
789791
return 0;
790792
}
@@ -850,7 +852,9 @@ setup_context(Py_ssize_t stack_level, PyObject **filename, int *lineno,
850852
}
851853
else {
852854
globals = f->f_globals;
853-
*filename = PyFrame_GetCode(f)->co_filename;
855+
PyCodeObject *code = PyFrame_GetCode(f);
856+
*filename = code->co_filename;
857+
Py_DECREF(code);
854858
Py_INCREF(*filename);
855859
*lineno = PyFrame_GetLineNumber(f);
856860
}

Python/import.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1557,6 +1557,7 @@ remove_importlib_frames(PyThreadState *tstate)
15571557
else {
15581558
prev_link = (PyObject **) &traceback->tb_next;
15591559
}
1560+
Py_DECREF(code);
15601561
tb = next;
15611562
}
15621563
done:

Python/traceback.c

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -581,6 +581,7 @@ tb_printinternal(PyTracebackObject *tb, PyObject *f, long limit)
581581
err = PyErr_CheckSignals();
582582
}
583583
}
584+
Py_DECREF(code);
584585
tb = tb->tb_next;
585586
}
586587
if (err == 0 && cnt > TB_RECURSIVE_CUTOFF) {
@@ -752,12 +753,9 @@ _Py_DumpASCII(int fd, PyObject *text)
752753
static void
753754
dump_frame(int fd, PyFrameObject *frame)
754755
{
755-
PyCodeObject *code;
756-
int lineno;
757-
758-
code = PyFrame_GetCode(frame);
756+
PyCodeObject *code = PyFrame_GetCode(frame);
759757
PUTS(fd, " File ");
760-
if (code != NULL && code->co_filename != NULL
758+
if (code->co_filename != NULL
761759
&& PyUnicode_Check(code->co_filename))
762760
{
763761
PUTS(fd, "\"");
@@ -768,7 +766,7 @@ dump_frame(int fd, PyFrameObject *frame)
768766
}
769767

770768
/* PyFrame_GetLineNumber() was introduced in Python 2.7.0 and 3.2.0 */
771-
lineno = PyCode_Addr2Line(code, frame->f_lasti);
769+
int lineno = PyCode_Addr2Line(code, frame->f_lasti);
772770
PUTS(fd, ", line ");
773771
if (lineno >= 0) {
774772
_Py_DumpDecimal(fd, (unsigned long)lineno);
@@ -778,7 +776,7 @@ dump_frame(int fd, PyFrameObject *frame)
778776
}
779777
PUTS(fd, " in ");
780778

781-
if (code != NULL && code->co_name != NULL
779+
if (code->co_name != NULL
782780
&& PyUnicode_Check(code->co_name)) {
783781
_Py_DumpASCII(fd, code->co_name);
784782
}
@@ -787,6 +785,7 @@ dump_frame(int fd, PyFrameObject *frame)
787785
}
788786

789787
PUTS(fd, "\n");
788+
Py_DECREF(code);
790789
}
791790

792791
static void

0 commit comments

Comments
 (0)