diff options
Diffstat (limited to 'Python/traceback.c')
-rw-r--r-- | Python/traceback.c | 43 |
1 files changed, 30 insertions, 13 deletions
diff --git a/Python/traceback.c b/Python/traceback.c index e53d87d..07a7ca8 100644 --- a/Python/traceback.c +++ b/Python/traceback.c @@ -99,10 +99,16 @@ tb_dir(PyObject *Py_UNUSED(self), PyObject *Py_UNUSED(ignored)) "tb_lasti", "tb_lineno"); } +/*[clinic input] +@critical_section +@getter +traceback.tb_next +[clinic start generated code]*/ + static PyObject * -tb_next_get(PyObject *op, void *Py_UNUSED(_)) +traceback_tb_next_get_impl(PyTracebackObject *self) +/*[clinic end generated code: output=963634df7d5fc837 input=8f6345f2b73cb965]*/ { - PyTracebackObject *self = _PyTracebackObject_CAST(op); PyObject* ret = (PyObject*)self->tb_next; if (!ret) { ret = Py_None; @@ -133,37 +139,48 @@ tb_lineno_get(PyObject *op, void *Py_UNUSED(_)) return PyLong_FromLong(lineno); } +/*[clinic input] +@critical_section +@setter +traceback.tb_next +[clinic start generated code]*/ + static int -tb_next_set(PyObject *op, PyObject *new_next, void *Py_UNUSED(_)) +traceback_tb_next_set_impl(PyTracebackObject *self, PyObject *value) +/*[clinic end generated code: output=d4868cbc48f2adac input=ce66367f85e3c443]*/ { - if (!new_next) { + if (!value) { PyErr_Format(PyExc_TypeError, "can't delete tb_next attribute"); return -1; } /* We accept None or a traceback object, and map None -> NULL (inverse of tb_next_get) */ - if (new_next == Py_None) { - new_next = NULL; - } else if (!PyTraceBack_Check(new_next)) { + if (value == Py_None) { + value = NULL; + } else if (!PyTraceBack_Check(value)) { PyErr_Format(PyExc_TypeError, "expected traceback object, got '%s'", - Py_TYPE(new_next)->tp_name); + Py_TYPE(value)->tp_name); return -1; } /* Check for loops */ - PyTracebackObject *self = _PyTracebackObject_CAST(op); - PyTracebackObject *cursor = (PyTracebackObject *)new_next; + PyTracebackObject *cursor = (PyTracebackObject *)value; + Py_XINCREF(cursor); while (cursor) { if (cursor == self) { PyErr_Format(PyExc_ValueError, "traceback loop detected"); + Py_DECREF(cursor); return -1; } - cursor = cursor->tb_next; + Py_BEGIN_CRITICAL_SECTION(cursor); + Py_XINCREF(cursor->tb_next); + Py_SETREF(cursor, cursor->tb_next); + Py_END_CRITICAL_SECTION(); } - Py_XSETREF(self->tb_next, (PyTracebackObject *)Py_XNewRef(new_next)); + Py_XSETREF(self->tb_next, (PyTracebackObject *)Py_XNewRef(value)); return 0; } @@ -181,7 +198,7 @@ static PyMemberDef tb_memberlist[] = { }; static PyGetSetDef tb_getsetters[] = { - {"tb_next", tb_next_get, tb_next_set, NULL, NULL}, + TRACEBACK_TB_NEXT_GETSETDEF {"tb_lineno", tb_lineno_get, NULL, NULL, NULL}, {NULL} /* Sentinel */ }; |