Skip to content

Commit 3c45240

Browse files
authored
bpo-33418: Add tp_clear for function object (GH-8058)
Without tp_clear, GC can't break cyclic reference. It will cause memory leak when cyclic reference is created intentionally.
1 parent d8cba5d commit 3c45240

File tree

2 files changed

+23
-13
lines changed

2 files changed

+23
-13
lines changed
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Fix potential memory leak in function object when it creates reference
2+
cycle.

Objects/funcobject.c

Lines changed: 21 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -523,23 +523,31 @@ func_new_impl(PyTypeObject *type, PyCodeObject *code, PyObject *globals,
523523
return (PyObject *)newfunc;
524524
}
525525

526+
static int
527+
func_clear(PyFunctionObject *op)
528+
{
529+
Py_CLEAR(op->func_code);
530+
Py_CLEAR(op->func_globals);
531+
Py_CLEAR(op->func_module);
532+
Py_CLEAR(op->func_name);
533+
Py_CLEAR(op->func_defaults);
534+
Py_CLEAR(op->func_kwdefaults);
535+
Py_CLEAR(op->func_doc);
536+
Py_CLEAR(op->func_dict);
537+
Py_CLEAR(op->func_closure);
538+
Py_CLEAR(op->func_annotations);
539+
Py_CLEAR(op->func_qualname);
540+
return 0;
541+
}
542+
526543
static void
527544
func_dealloc(PyFunctionObject *op)
528545
{
529546
_PyObject_GC_UNTRACK(op);
530-
if (op->func_weakreflist != NULL)
547+
if (op->func_weakreflist != NULL) {
531548
PyObject_ClearWeakRefs((PyObject *) op);
532-
Py_DECREF(op->func_code);
533-
Py_DECREF(op->func_globals);
534-
Py_XDECREF(op->func_module);
535-
Py_DECREF(op->func_name);
536-
Py_XDECREF(op->func_defaults);
537-
Py_XDECREF(op->func_kwdefaults);
538-
Py_XDECREF(op->func_doc);
539-
Py_XDECREF(op->func_dict);
540-
Py_XDECREF(op->func_closure);
541-
Py_XDECREF(op->func_annotations);
542-
Py_XDECREF(op->func_qualname);
549+
}
550+
(void)func_clear(op);
543551
PyObject_GC_Del(op);
544552
}
545553

@@ -612,7 +620,7 @@ PyTypeObject PyFunction_Type = {
612620
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
613621
func_new__doc__, /* tp_doc */
614622
(traverseproc)func_traverse, /* tp_traverse */
615-
0, /* tp_clear */
623+
(inquiry)func_clear, /* tp_clear */
616624
0, /* tp_richcompare */
617625
offsetof(PyFunctionObject, func_weakreflist), /* tp_weaklistoffset */
618626
0, /* tp_iter */

0 commit comments

Comments
 (0)