# include "pycore_gc.h" // PyGC_Head
# include "pycore_runtime.h" // _Py_ID()
#endif
+#include "pycore_critical_section.h"// Py_BEGIN_CRITICAL_SECTION()
#include "pycore_modsupport.h" // _PyArg_UnpackKeywords()
PyDoc_STRVAR(tb_new__doc__,
exit:
return return_value;
}
-/*[clinic end generated code: output=62ebc0196940f663 input=a9049054013a1b77]*/
+
+#if !defined(traceback_tb_next_DOCSTR)
+# define traceback_tb_next_DOCSTR NULL
+#endif
+#if defined(TRACEBACK_TB_NEXT_GETSETDEF)
+# undef TRACEBACK_TB_NEXT_GETSETDEF
+# define TRACEBACK_TB_NEXT_GETSETDEF {"tb_next", (getter)traceback_tb_next_get, (setter)traceback_tb_next_set, traceback_tb_next_DOCSTR},
+#else
+# define TRACEBACK_TB_NEXT_GETSETDEF {"tb_next", (getter)traceback_tb_next_get, NULL, traceback_tb_next_DOCSTR},
+#endif
+
+static PyObject *
+traceback_tb_next_get_impl(PyTracebackObject *self);
+
+static PyObject *
+traceback_tb_next_get(PyObject *self, void *Py_UNUSED(context))
+{
+ PyObject *return_value = NULL;
+
+ Py_BEGIN_CRITICAL_SECTION(self);
+ return_value = traceback_tb_next_get_impl((PyTracebackObject *)self);
+ Py_END_CRITICAL_SECTION();
+
+ return return_value;
+}
+
+#if !defined(traceback_tb_next_DOCSTR)
+# define traceback_tb_next_DOCSTR NULL
+#endif
+#if defined(TRACEBACK_TB_NEXT_GETSETDEF)
+# undef TRACEBACK_TB_NEXT_GETSETDEF
+# define TRACEBACK_TB_NEXT_GETSETDEF {"tb_next", (getter)traceback_tb_next_get, (setter)traceback_tb_next_set, traceback_tb_next_DOCSTR},
+#else
+# define TRACEBACK_TB_NEXT_GETSETDEF {"tb_next", NULL, (setter)traceback_tb_next_set, NULL},
+#endif
+
+static int
+traceback_tb_next_set_impl(PyTracebackObject *self, PyObject *value);
+
+static int
+traceback_tb_next_set(PyObject *self, PyObject *value, void *Py_UNUSED(context))
+{
+ int return_value;
+
+ Py_BEGIN_CRITICAL_SECTION(self);
+ return_value = traceback_tb_next_set_impl((PyTracebackObject *)self, value);
+ Py_END_CRITICAL_SECTION();
+
+ return return_value;
+}
+/*[clinic end generated code: output=ca43786e235e38f4 input=a9049054013a1b77]*/
"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;
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;
}
};
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 */
};