From 6d2f4f59f82b09445ea32367e10918ae13b4b9e0 Mon Sep 17 00:00:00 2001 From: microDev <70126934+microDev1@users.noreply.github.com> Date: Wed, 10 Nov 2021 16:12:42 +0530 Subject: [PATCH] refactor traceback handling --- py/mpstate.h | 4 ---- py/objexcept.c | 29 +++++++++++++++-------------- py/runtime.c | 6 ++---- py/scheduler.c | 2 +- 4 files changed, 18 insertions(+), 23 deletions(-) diff --git a/py/mpstate.h b/py/mpstate.h index 2f9dafd925..964a04f300 100644 --- a/py/mpstate.h +++ b/py/mpstate.h @@ -140,14 +140,10 @@ typedef struct _mp_state_vm_t { #if MICROPY_KBD_EXCEPTION // exception object of type KeyboardInterrupt mp_obj_exception_t mp_kbd_exception; - // traceback object to store traceback - mp_obj_traceback_t mp_kbd_traceback; #endif // exception object of type ReloadException mp_obj_exception_t mp_reload_exception; - // traceback object to store traceback - mp_obj_traceback_t mp_reload_traceback; // dictionary with loaded modules (may be exposed as sys.modules) mp_obj_dict_t mp_loaded_modules_dict; diff --git a/py/objexcept.c b/py/objexcept.c index c7e5cb7675..b8d7692b18 100644 --- a/py/objexcept.c +++ b/py/objexcept.c @@ -166,15 +166,7 @@ mp_obj_t mp_obj_exception_make_new(const mp_obj_type_t *type, size_t n_args, siz // Populate the exception object o_exc->base.type = type; - - // Try to allocate memory for the traceback, with fallback to emergency traceback object - o_exc->traceback = m_new_obj_maybe(mp_obj_traceback_t); - if (o_exc->traceback == NULL) { - o_exc->traceback = &MP_STATE_VM(mp_emergency_traceback_obj); - } - - // Populate the traceback object - *o_exc->traceback = mp_const_empty_traceback_obj; + o_exc->traceback = (mp_obj_traceback_t *)&mp_const_empty_traceback_obj; mp_obj_tuple_t *o_tuple; if (n_args == 0) { @@ -228,7 +220,7 @@ void mp_obj_exception_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) { // store/delete attribute if (attr == MP_QSTR___traceback__) { if (dest[1] == mp_const_none) { - self->traceback->data = NULL; + self->traceback = (mp_obj_traceback_t *)&mp_const_empty_traceback_obj; } else { if (!mp_obj_is_type(dest[1], &mp_type_traceback)) { mp_raise_TypeError(MP_ERROR_TEXT("invalid traceback")); @@ -244,7 +236,7 @@ void mp_obj_exception_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) { } else if (attr == MP_QSTR_value && self->base.type == &mp_type_StopIteration) { dest[0] = mp_obj_exception_get_value(self_in); } else if (attr == MP_QSTR___traceback__) { - dest[0] = (self->traceback->data) ? MP_OBJ_FROM_PTR(self->traceback) : mp_const_none; + dest[0] = (self->traceback) ? MP_OBJ_FROM_PTR(self->traceback) : mp_const_none; #if MICROPY_CPYTHON_COMPAT } else if (mp_obj_is_subclass_fast(MP_OBJ_FROM_PTR(self->base.type), MP_OBJ_FROM_PTR(&mp_type_OSError))) { if (attr == MP_QSTR_errno) { @@ -552,14 +544,23 @@ bool mp_obj_exception_match(mp_obj_t exc, mp_const_obj_t exc_type) { void mp_obj_exception_clear_traceback(mp_obj_t self_in) { mp_obj_exception_t *self = get_native_exception(self_in); - // just set the traceback to the null object + // just set the traceback to the empty traceback object // we don't want to call any memory management functions here - self->traceback->data = NULL; + self->traceback = (mp_obj_traceback_t *)&mp_const_empty_traceback_obj; } void mp_obj_exception_add_traceback(mp_obj_t self_in, qstr file, size_t line, qstr block) { mp_obj_exception_t *self = get_native_exception(self_in); + // Try to allocate memory for the traceback, with fallback to emergency traceback object + + if (self->traceback == NULL || self->traceback == (mp_obj_traceback_t *)&mp_const_empty_traceback_obj) { + self->traceback = m_new_obj_maybe(mp_obj_traceback_t); + if (self->traceback == NULL) { + self->traceback = &MP_STATE_VM(mp_emergency_traceback_obj); + } + } + // append this traceback info to traceback data // if memory allocation fails (eg because gc is locked), just return @@ -613,7 +614,7 @@ void mp_obj_exception_add_traceback(mp_obj_t self_in, qstr file, size_t line, qs void mp_obj_exception_get_traceback(mp_obj_t self_in, size_t *n, size_t **values) { mp_obj_exception_t *self = get_native_exception(self_in); - if (self->traceback->data == NULL) { + if (self->traceback == NULL) { *n = 0; *values = NULL; } else { diff --git a/py/runtime.c b/py/runtime.c index ac02f7074c..1554a70231 100644 --- a/py/runtime.c +++ b/py/runtime.c @@ -80,14 +80,12 @@ void mp_init(void) { // initialise the exception object for raising KeyboardInterrupt MP_STATE_VM(mp_kbd_exception).base.type = &mp_type_KeyboardInterrupt; MP_STATE_VM(mp_kbd_exception).args = (mp_obj_tuple_t *)&mp_const_empty_tuple_obj; - MP_STATE_VM(mp_kbd_exception).traceback = &MP_STATE_VM(mp_kbd_traceback); - *MP_STATE_VM(mp_kbd_exception).traceback = mp_const_empty_traceback_obj; + MP_STATE_VM(mp_kbd_exception).traceback = (mp_obj_traceback_t *)&mp_const_empty_traceback_obj; #endif MP_STATE_VM(mp_reload_exception).base.type = &mp_type_ReloadException; MP_STATE_VM(mp_reload_exception).args = (mp_obj_tuple_t *)&mp_const_empty_tuple_obj; - MP_STATE_VM(mp_reload_exception).traceback = &MP_STATE_VM(mp_reload_traceback); - *MP_STATE_VM(mp_reload_exception).traceback = mp_const_empty_traceback_obj; + MP_STATE_VM(mp_reload_exception).traceback = (mp_obj_traceback_t *)&mp_const_empty_traceback_obj; // call port specific initialization if any #ifdef MICROPY_PORT_INIT_FUNC diff --git a/py/scheduler.c b/py/scheduler.c index 8e150f41ed..1fd5daeab1 100644 --- a/py/scheduler.c +++ b/py/scheduler.c @@ -42,7 +42,7 @@ void MICROPY_WRAP_MP_SCHED_EXCEPTION(mp_sched_exception)(mp_obj_t exc) { #if MICROPY_KBD_EXCEPTION // This function may be called asynchronously at any time so only do the bare minimum. void MICROPY_WRAP_MP_SCHED_KEYBOARD_INTERRUPT(mp_sched_keyboard_interrupt)(void) { - MP_STATE_VM(mp_kbd_exception).traceback->data = NULL; + MP_STATE_VM(mp_kbd_exception).traceback = (mp_obj_traceback_t *)&mp_const_empty_traceback_obj; mp_sched_exception(MP_OBJ_FROM_PTR(&MP_STATE_VM(mp_kbd_exception))); } #endif