@@ -99,10 +99,16 @@ tb_dir(PyObject *Py_UNUSED(self), PyObject *Py_UNUSED(ignored))
99
99
"tb_lasti" , "tb_lineno" );
100
100
}
101
101
102
+ /*[clinic input]
103
+ @critical_section
104
+ @getter
105
+ traceback.tb_next
106
+ [clinic start generated code]*/
107
+
102
108
static 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]*/
104
111
{
105
- PyTracebackObject * self = _PyTracebackObject_CAST (op );
106
112
PyObject * ret = (PyObject * )self -> tb_next ;
107
113
if (!ret ) {
108
114
ret = Py_None ;
@@ -133,37 +139,48 @@ tb_lineno_get(PyObject *op, void *Py_UNUSED(_))
133
139
return PyLong_FromLong (lineno );
134
140
}
135
141
142
+ /*[clinic input]
143
+ @critical_section
144
+ @setter
145
+ traceback.tb_next
146
+ [clinic start generated code]*/
147
+
136
148
static 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]*/
138
151
{
139
- if (!new_next ) {
152
+ if (!value ) {
140
153
PyErr_Format (PyExc_TypeError , "can't delete tb_next attribute" );
141
154
return -1 ;
142
155
}
143
156
144
157
/* We accept None or a traceback object, and map None -> NULL (inverse of
145
158
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 )) {
149
162
PyErr_Format (PyExc_TypeError ,
150
163
"expected traceback object, got '%s'" ,
151
- Py_TYPE (new_next )-> tp_name );
164
+ Py_TYPE (value )-> tp_name );
152
165
return -1 ;
153
166
}
154
167
155
168
/* Check for loops */
156
- PyTracebackObject * self = _PyTracebackObject_CAST ( op ) ;
157
- PyTracebackObject * cursor = ( PyTracebackObject * ) new_next ;
169
+ PyTracebackObject * cursor = ( PyTracebackObject * ) value ;
170
+ Py_XINCREF ( cursor ) ;
158
171
while (cursor ) {
159
172
if (cursor == self ) {
160
173
PyErr_Format (PyExc_ValueError , "traceback loop detected" );
174
+ Py_DECREF (cursor );
161
175
return -1 ;
162
176
}
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 ();
164
181
}
165
182
166
- Py_XSETREF (self -> tb_next , (PyTracebackObject * )Py_XNewRef (new_next ));
183
+ Py_XSETREF (self -> tb_next , (PyTracebackObject * )Py_XNewRef (value ));
167
184
168
185
return 0 ;
169
186
}
@@ -181,7 +198,7 @@ static PyMemberDef tb_memberlist[] = {
181
198
};
182
199
183
200
static PyGetSetDef tb_getsetters [] = {
184
- { "tb_next" , tb_next_get , tb_next_set , NULL , NULL },
201
+ TRACEBACK_TB_NEXT_GETSETDEF
185
202
{"tb_lineno" , tb_lineno_get , NULL , NULL , NULL },
186
203
{NULL } /* Sentinel */
187
204
};
0 commit comments