8
8
9
9
#include "capi.h" // GraalPy change
10
10
#include "Python.h"
11
- #if 0 // GraalPy change
12
11
#include "pycore_call.h" // _PyObject_CallNoArgs()
12
+ #if 0 // GraalPy change
13
13
#include "pycore_initconfig.h" // _PyStatus_ERR()
14
14
#endif // GraalPy change
15
15
#include "pycore_pyerrors.h" // _PyErr_Format()
@@ -68,6 +68,7 @@ _PyErr_GetTopmostException(PyThreadState *tstate)
68
68
}
69
69
return exc_info ;
70
70
}
71
+ #endif // GraalPy change
71
72
72
73
static PyObject *
73
74
_PyErr_CreateException (PyObject * exception_type , PyObject * value )
@@ -94,7 +95,6 @@ _PyErr_CreateException(PyObject *exception_type, PyObject *value)
94
95
95
96
return exc ;
96
97
}
97
- #endif // GraalPy change
98
98
99
99
void
100
100
_PyErr_SetObject (PyThreadState * tstate , PyObject * exception , PyObject * value )
@@ -234,9 +234,107 @@ void
234
234
_PyErr_NormalizeException (PyThreadState * tstate , PyObject * * exc ,
235
235
PyObject * * val , PyObject * * tb )
236
236
{
237
- // GraalPy change: nothing to do here from our side, the exception is already
238
- // reified
237
+ int recursion_depth = 0 ;
238
+ // GraalPy change: we don't have recursion_headroom
239
+ // tstate->recursion_headroom++;
240
+ PyObject * type , * value , * initial_tb ;
241
+
242
+ restart :
243
+ type = * exc ;
244
+ if (type == NULL ) {
245
+ /* There was no exception, so nothing to do. */
246
+ // tstate->recursion_headroom--;
247
+ return ;
248
+ }
249
+
250
+ value = * val ;
251
+ /* If PyErr_SetNone() was used, the value will have been actually
252
+ set to NULL.
253
+ */
254
+ if (!value ) {
255
+ value = Py_None ;
256
+ Py_INCREF (value );
257
+ }
258
+
259
+ /* Normalize the exception so that if the type is a class, the
260
+ value will be an instance.
261
+ */
262
+ if (PyExceptionClass_Check (type )) {
263
+ PyObject * inclass = NULL ;
264
+ int is_subclass = 0 ;
265
+
266
+ if (PyExceptionInstance_Check (value )) {
267
+ inclass = PyExceptionInstance_Class (value );
268
+ is_subclass = PyObject_IsSubclass (inclass , type );
269
+ if (is_subclass < 0 ) {
270
+ goto error ;
271
+ }
272
+ }
273
+
274
+ /* If the value was not an instance, or is not an instance
275
+ whose class is (or is derived from) type, then use the
276
+ value as an argument to instantiation of the type
277
+ class.
278
+ */
279
+ if (!is_subclass ) {
280
+ PyObject * fixed_value = _PyErr_CreateException (type , value );
281
+ if (fixed_value == NULL ) {
282
+ goto error ;
283
+ }
284
+ Py_DECREF (value );
285
+ value = fixed_value ;
286
+ }
287
+ /* If the class of the instance doesn't exactly match the
288
+ class of the type, believe the instance.
289
+ */
290
+ else if (inclass != type ) {
291
+ Py_INCREF (inclass );
292
+ Py_DECREF (type );
293
+ type = inclass ;
294
+ }
295
+ }
296
+ * exc = type ;
297
+ * val = value ;
298
+ // tstate->recursion_headroom--;
239
299
return ;
300
+
301
+ error :
302
+ Py_DECREF (type );
303
+ Py_DECREF (value );
304
+ recursion_depth ++ ;
305
+ if (recursion_depth == Py_NORMALIZE_RECURSION_LIMIT ) {
306
+ _PyErr_SetString (tstate , PyExc_RecursionError ,
307
+ "maximum recursion depth exceeded "
308
+ "while normalizing an exception" );
309
+ }
310
+ /* If the new exception doesn't set a traceback and the old
311
+ exception had a traceback, use the old traceback for the
312
+ new exception. It's better than nothing.
313
+ */
314
+ initial_tb = * tb ;
315
+ _PyErr_Fetch (tstate , exc , val , tb );
316
+ assert (* exc != NULL );
317
+ if (initial_tb != NULL ) {
318
+ if (* tb == NULL )
319
+ * tb = initial_tb ;
320
+ else
321
+ Py_DECREF (initial_tb );
322
+ }
323
+ /* Abort when Py_NORMALIZE_RECURSION_LIMIT has been exceeded, and the
324
+ corresponding RecursionError could not be normalized, and the
325
+ MemoryError raised when normalize this RecursionError could not be
326
+ normalized. */
327
+ if (recursion_depth >= Py_NORMALIZE_RECURSION_LIMIT + 2 ) {
328
+ if (PyErr_GivenExceptionMatches (* exc , PyExc_MemoryError )) {
329
+ Py_FatalError ("Cannot recover from MemoryErrors "
330
+ "while normalizing exceptions." );
331
+ }
332
+ else {
333
+ Py_FatalError ("Cannot recover from the recursive normalization "
334
+ "of an exception." );
335
+ }
336
+ }
337
+ goto restart ;
240
338
}
241
339
242
340
0 commit comments