@@ -99,10 +99,16 @@ tb_dir(PyObject *Py_UNUSED(self), PyObject *Py_UNUSED(ignored))
9999"tb_lasti", "tb_lineno");
100100}
101101102+/*[clinic input]
103+@critical_section
104+@getter
105+traceback.tb_next
106+[clinic start generated code]*/
107+102108staticPyObject*
103-tb_next_get(PyObject*op, void*Py_UNUSED(_))
109+traceback_tb_next_get_impl(PyTracebackObject*self)
110+/*[clinic end generated code: output=963634df7d5fc837 input=8f6345f2b73cb965]*/
104111{
105-PyTracebackObject*self=_PyTracebackObject_CAST(op);
106112PyObject*ret= (PyObject*)self->tb_next;
107113if (!ret) {
108114ret=Py_None;
@@ -133,37 +139,48 @@ tb_lineno_get(PyObject *op, void *Py_UNUSED(_))
133139returnPyLong_FromLong(lineno);
134140}
135141142+/*[clinic input]
143+@critical_section
144+@setter
145+traceback.tb_next
146+[clinic start generated code]*/
147+136148staticint
137-tb_next_set(PyObject*op, PyObject*new_next, void*Py_UNUSED(_))
149+traceback_tb_next_set_impl(PyTracebackObject*self, PyObject*value)
150+/*[clinic end generated code: output=d4868cbc48f2adac input=ce66367f85e3c443]*/
138151{
139-if (!new_next) {
152+if (!value) {
140153PyErr_Format(PyExc_TypeError, "can't delete tb_next attribute");
141154return-1;
142155 }
143156144157/* We accept None or a traceback object, and map None -> NULL (inverse of
145158 tb_next_get) */
146-if (new_next==Py_None) {
147-new_next=NULL;
148- } elseif (!PyTraceBack_Check(new_next)) {
159+if (value==Py_None) {
160+value=NULL;
161+ } elseif (!PyTraceBack_Check(value)) {
149162PyErr_Format(PyExc_TypeError,
150163"expected traceback object, got '%s'",
151-Py_TYPE(new_next)->tp_name);
164+Py_TYPE(value)->tp_name);
152165return-1;
153166 }
154167155168/* Check for loops */
156-PyTracebackObject*self=_PyTracebackObject_CAST(op);
157-PyTracebackObject*cursor= (PyTracebackObject*)new_next;
169+PyTracebackObject*cursor=(PyTracebackObject*)value;
170+Py_XINCREF(cursor);
158171while (cursor) {
159172if (cursor==self) {
160173PyErr_Format(PyExc_ValueError, "traceback loop detected");
174+Py_DECREF(cursor);
161175return-1;
162176 }
163-cursor=cursor->tb_next;
177+Py_BEGIN_CRITICAL_SECTION(cursor);
178+Py_XINCREF(cursor->tb_next);
179+Py_SETREF(cursor, cursor->tb_next);
180+Py_END_CRITICAL_SECTION();
164181 }
165182166-Py_XSETREF(self->tb_next, (PyTracebackObject*)Py_XNewRef(new_next));
183+Py_XSETREF(self->tb_next, (PyTracebackObject*)Py_XNewRef(value));
167184168185return0;
169186}
@@ -181,7 +198,7 @@ static PyMemberDef tb_memberlist[] = {
181198};
182199183200staticPyGetSetDeftb_getsetters[] = {
184-{"tb_next", tb_next_get, tb_next_set, NULL, NULL},
201+TRACEBACK_TB_NEXT_GETSETDEF
185202 {"tb_lineno", tb_lineno_get, NULL, NULL, NULL},
186203 {NULL} /* Sentinel */
187204};