mirror of
https://github.com/python/cpython.git
synced 2025-09-27 02:39:58 +00:00
Make traceback objects collectable.
This should eliminate the traceback returned by sys.exc_info() as a common source of memory leaks.
This commit is contained in:
parent
d703057752
commit
fd14d8e187
1 changed files with 46 additions and 2 deletions
|
@ -36,12 +36,36 @@ static void
|
||||||
tb_dealloc(tracebackobject *tb)
|
tb_dealloc(tracebackobject *tb)
|
||||||
{
|
{
|
||||||
Py_TRASHCAN_SAFE_BEGIN(tb)
|
Py_TRASHCAN_SAFE_BEGIN(tb)
|
||||||
|
_PyObject_GC_UNTRACK(tb);
|
||||||
Py_XDECREF(tb->tb_next);
|
Py_XDECREF(tb->tb_next);
|
||||||
Py_XDECREF(tb->tb_frame);
|
Py_XDECREF(tb->tb_frame);
|
||||||
PyObject_DEL(tb);
|
PyObject_GC_Del(tb);
|
||||||
Py_TRASHCAN_SAFE_END(tb)
|
Py_TRASHCAN_SAFE_END(tb)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
tb_traverse(tracebackobject *tb, visitproc visit, void *arg)
|
||||||
|
{
|
||||||
|
int err = 0;
|
||||||
|
if (tb->tb_next) {
|
||||||
|
err = visit((PyObject *)tb->tb_next, arg);
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
if (tb->tb_frame)
|
||||||
|
err = visit((PyObject *)tb->tb_frame, arg);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
tb_clear(tracebackobject *tb)
|
||||||
|
{
|
||||||
|
Py_XDECREF(tb->tb_next);
|
||||||
|
Py_XDECREF(tb->tb_frame);
|
||||||
|
tb->tb_next = NULL;
|
||||||
|
tb->tb_frame = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
PyTypeObject PyTraceBack_Type = {
|
PyTypeObject PyTraceBack_Type = {
|
||||||
PyObject_HEAD_INIT(&PyType_Type)
|
PyObject_HEAD_INIT(&PyType_Type)
|
||||||
0,
|
0,
|
||||||
|
@ -57,6 +81,25 @@ PyTypeObject PyTraceBack_Type = {
|
||||||
0, /*tp_as_number*/
|
0, /*tp_as_number*/
|
||||||
0, /*tp_as_sequence*/
|
0, /*tp_as_sequence*/
|
||||||
0, /*tp_as_mapping*/
|
0, /*tp_as_mapping*/
|
||||||
|
0, /* tp_hash */
|
||||||
|
0, /* tp_call */
|
||||||
|
0, /* tp_str */
|
||||||
|
0, /* tp_getattro */
|
||||||
|
0, /* tp_setattro */
|
||||||
|
0, /* tp_as_buffer */
|
||||||
|
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */
|
||||||
|
0, /* tp_doc */
|
||||||
|
(traverseproc)tb_traverse, /* tp_traverse */
|
||||||
|
(inquiry)tb_clear, /* tp_clear */
|
||||||
|
0, /* tp_richcompare */
|
||||||
|
0, /* tp_weaklistoffset */
|
||||||
|
0, /* tp_iter */
|
||||||
|
0, /* tp_iternext */
|
||||||
|
0, /* tp_methods */
|
||||||
|
0, /* tp_members */
|
||||||
|
0, /* tp_getset */
|
||||||
|
0, /* tp_base */
|
||||||
|
0, /* tp_dict */
|
||||||
};
|
};
|
||||||
|
|
||||||
static tracebackobject *
|
static tracebackobject *
|
||||||
|
@ -69,7 +112,7 @@ newtracebackobject(tracebackobject *next, PyFrameObject *frame, int lasti,
|
||||||
PyErr_BadInternalCall();
|
PyErr_BadInternalCall();
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
tb = PyObject_NEW(tracebackobject, &PyTraceBack_Type);
|
tb = PyObject_GC_New(tracebackobject, &PyTraceBack_Type);
|
||||||
if (tb != NULL) {
|
if (tb != NULL) {
|
||||||
Py_XINCREF(next);
|
Py_XINCREF(next);
|
||||||
tb->tb_next = next;
|
tb->tb_next = next;
|
||||||
|
@ -77,6 +120,7 @@ newtracebackobject(tracebackobject *next, PyFrameObject *frame, int lasti,
|
||||||
tb->tb_frame = frame;
|
tb->tb_frame = frame;
|
||||||
tb->tb_lasti = lasti;
|
tb->tb_lasti = lasti;
|
||||||
tb->tb_lineno = lineno;
|
tb->tb_lineno = lineno;
|
||||||
|
_PyObject_GC_TRACK(tb);
|
||||||
}
|
}
|
||||||
return tb;
|
return tb;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue