@@ -99,10 +99,16 @@ tb_dir(PyObject *Py_UNUSED(self), PyObject *Py_UNUSED(ignored))
9999"tb_lasti" , "tb_lineno" );
100100}
101101
102+ /*[clinic input]
103+ @critical_section
104+ @getter
105+ traceback.tb_next
106+ [clinic start generated code]*/
107+
102108static PyObject *
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(_))
133139return PyLong_FromLong (lineno );
134140}
135141
142+ /*[clinic input]
143+ @critical_section
144+ @setter
145+ traceback.tb_next
146+ [clinic start generated code]*/
147+
136148static int
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 }
143156
144157/* 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- } else if (!PyTraceBack_Check (new_next )){
159+ if (value == Py_None ){
160+ value = NULL ;
161+ } else if (!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 }
154167
155168/* 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 }
165182
166- Py_XSETREF (self -> tb_next , (PyTracebackObject * )Py_XNewRef (new_next ));
183+ Py_XSETREF (self -> tb_next , (PyTracebackObject * )Py_XNewRef (value ));
167184
168185return 0 ;
169186}
@@ -181,7 +198,7 @@ static PyMemberDef tb_memberlist[] ={
181198};
182199
183200static PyGetSetDef tb_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};
0 commit comments