@@ -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 );
106112    PyObject *  ret  =  (PyObject * )self -> tb_next ;
107113    if  (!ret ) {
108114        ret  =  Py_None ;
@@ -133,37 +139,48 @@ tb_lineno_get(PyObject *op, void *Py_UNUSED(_))
133139    return  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 ) {
140153        PyErr_Format (PyExc_TypeError , "can't delete tb_next attribute" );
141154        return  -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 )) {
149162        PyErr_Format (PyExc_TypeError ,
150163                     "expected traceback object, got '%s'" ,
151-                      Py_TYPE (new_next )-> tp_name );
164+                      Py_TYPE (value )-> tp_name );
152165        return  -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 ) ;
158171    while  (cursor ) {
159172        if  (cursor  ==  self ) {
160173            PyErr_Format (PyExc_ValueError , "traceback loop detected" );
174+             Py_DECREF (cursor );
161175            return  -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
168185    return  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