do not chain exceptions to themselves

cpython actually makes sure the newly chained exception doesn't create
a cycle (even indirectly); see _PyErr_SetObject use of "Floyd's cycle
detection algo". We'll go for the simpler solution of just checking
one level deep until it's clear we need to do more.

Closes: #7414
This commit is contained in:
Jeff Epler 2023-01-04 08:32:59 -06:00
parent 4cc7466617
commit cc16bd3d53
No known key found for this signature in database
GPG Key ID: D5BF15AB975AB4DE
3 changed files with 28 additions and 3 deletions

View File

@ -1150,7 +1150,7 @@ unwind_return:
mp_obj_t obj = mp_make_raise_obj(TOP());
#if MICROPY_CPYTHON_EXCEPTION_CHAIN
mp_obj_t active_exception = get_active_exception(exc_sp, exc_stack);
if (active_exception != MP_OBJ_NULL) {
if (active_exception != MP_OBJ_NULL && active_exception != obj) {
mp_store_attr(obj, MP_QSTR___context__, active_exception);
}
#endif
@ -1164,7 +1164,7 @@ unwind_return:
#if MICROPY_CPYTHON_EXCEPTION_CHAIN
// search for the inner-most previous exception, to chain it
mp_obj_t active_exception = get_active_exception(exc_sp, exc_stack);
if (active_exception != MP_OBJ_NULL) {
if (active_exception != MP_OBJ_NULL && active_exception != obj) {
mp_store_attr(obj, MP_QSTR___context__, active_exception);
}
mp_store_attr(obj, MP_QSTR___cause__, cause);
@ -1463,7 +1463,7 @@ unwind_loop:
exc_sp->prev_exc = nlr.ret_val;
mp_obj_t obj = MP_OBJ_FROM_PTR(nlr.ret_val);
#if MICROPY_CPYTHON_EXCEPTION_CHAIN
if (active_exception != MP_OBJ_NULL) {
if (active_exception != MP_OBJ_NULL && active_exception != obj) {
mp_store_attr(obj, MP_QSTR___context__, active_exception);
}
#endif

View File

@ -62,3 +62,13 @@ try:
1 / 0
except Exception as e:
print_exc_info(e)
try:
try:
1 / 0
except Exception as inner:
raise inner
except Exception as e:
print_exc_info(e, chain=False)
print_exc_info(e)
print()

View File

@ -59,3 +59,18 @@ Traceback (most recent call last):
ZeroDivisionError: division by zero
------------------------------------------------------------------------
------------------------------------------------------------------------
Traceback (most recent call last):
File "circuitpython/traceback_test_chained.py", line 70, in <module>
File "circuitpython/traceback_test_chained.py", line 68, in <module>
ZeroDivisionError: division by zero
------------------------------------------------------------------------
------------------------------------------------------------------------
Traceback (most recent call last):
File "circuitpython/traceback_test_chained.py", line 70, in <module>
File "circuitpython/traceback_test_chained.py", line 68, in <module>
ZeroDivisionError: division by zero
------------------------------------------------------------------------