diff options
| -rw-r--r-- | py/mpconfig.h | 10 | ||||
| -rw-r--r-- | shared/runtime/pyexec.c | 42 | ||||
| -rw-r--r-- | shared/runtime/pyexec.h | 11 |
3 files changed, 57 insertions, 6 deletions
diff --git a/py/mpconfig.h b/py/mpconfig.h index 6ad27c51f..97c40389b 100644 --- a/py/mpconfig.h +++ b/py/mpconfig.h @@ -1180,6 +1180,16 @@ typedef time_t mp_timestamp_t; #define MICROPY_ENABLE_VM_ABORT (0) #endif +// Whether to handle abort behavior in pyexec code +#ifndef MICROPY_PYEXEC_ENABLE_VM_ABORT +#define MICROPY_PYEXEC_ENABLE_VM_ABORT (0) +#endif + +// Whether to set exit codes according to the exit reason (keyboard interrupt, crash, normal exit, ...) +#ifndef MICROPY_PYEXEC_ENABLE_EXIT_CODE_HANDLING +#define MICROPY_PYEXEC_ENABLE_EXIT_CODE_HANDLING (0) +#endif + // Support for internal scheduler #ifndef MICROPY_ENABLE_SCHEDULER #define MICROPY_ENABLE_SCHEDULER (MICROPY_CONFIG_ROM_LEVEL_AT_LEAST_EXTRA_FEATURES) diff --git a/shared/runtime/pyexec.c b/shared/runtime/pyexec.c index 7d2a70c01..cf17bd0dc 100644 --- a/shared/runtime/pyexec.c +++ b/shared/runtime/pyexec.c @@ -72,6 +72,10 @@ static int parse_compile_execute(const void *source, mp_parse_input_kind_t input nlr_buf_t nlr; nlr.ret_val = NULL; if (nlr_push(&nlr) == 0) { + #if MICROPY_PYEXEC_ENABLE_VM_ABORT + nlr_set_abort(&nlr); + #endif + mp_obj_t module_fun; #if MICROPY_MODULE_FROZEN_MPY if (exec_flags & EXEC_FLAG_SOURCE_IS_RAW_CODE) { @@ -116,7 +120,7 @@ static int parse_compile_execute(const void *source, mp_parse_input_kind_t input mp_hal_set_interrupt_char(-1); // disable interrupt mp_handle_pending(true); // handle any pending exceptions (and any callbacks) nlr_pop(); - ret = 1; + ret = PYEXEC_NORMAL_EXIT; if (exec_flags & EXEC_FLAG_PRINT_EOF) { mp_hal_stdout_tx_strn("\x04", 1); } @@ -135,15 +139,41 @@ static int parse_compile_execute(const void *source, mp_parse_input_kind_t input mp_hal_stdout_tx_strn("\x04", 1); } - // check for SystemExit - if (mp_obj_is_subclass_fast(MP_OBJ_FROM_PTR(((mp_obj_base_t *)nlr.ret_val)->type), MP_OBJ_FROM_PTR(&mp_type_SystemExit))) { - // at the moment, the value of SystemExit is unused + #if MICROPY_PYEXEC_ENABLE_VM_ABORT + if (nlr.ret_val == NULL) { // abort + ret = PYEXEC_ABORT; + } else + #endif + if (mp_obj_is_subclass_fast(MP_OBJ_FROM_PTR(((mp_obj_base_t *)nlr.ret_val)->type), MP_OBJ_FROM_PTR(&mp_type_SystemExit))) { // system exit + #if MICROPY_PYEXEC_ENABLE_EXIT_CODE_HANDLING + mp_obj_t val = mp_obj_exception_get_value(MP_OBJ_FROM_PTR(nlr.ret_val)); + if (val != mp_const_none) { + if (mp_obj_is_int(val)) { + ret = (int)mp_obj_int_get_truncated(val); + } else { + mp_obj_print_helper(MICROPY_ERROR_PRINTER, val, PRINT_STR); + mp_print_str(MICROPY_ERROR_PRINTER, "\n"); + ret = PYEXEC_UNHANDLED_EXCEPTION; + } + } else { + ret = PYEXEC_NORMAL_EXIT; + } + #else ret = PYEXEC_FORCED_EXIT; - } else { + #endif + } else { // other exception mp_obj_print_exception(&mp_plat_print, MP_OBJ_FROM_PTR(nlr.ret_val)); - ret = 0; + ret = PYEXEC_UNHANDLED_EXCEPTION; + #if MICROPY_PYEXEC_ENABLE_EXIT_CODE_HANDLING + if (mp_obj_is_subclass_fast(MP_OBJ_FROM_PTR(((mp_obj_base_t *)nlr.ret_val)->type), MP_OBJ_FROM_PTR(&mp_type_KeyboardInterrupt))) { // keyboard interrupt + ret = PYEXEC_KEYBOARD_INTERRUPT; + } + #endif } } + #if MICROPY_PYEXEC_ENABLE_VM_ABORT + nlr_set_abort(NULL); + #endif #if MICROPY_REPL_INFO // display debugging info if wanted diff --git a/shared/runtime/pyexec.h b/shared/runtime/pyexec.h index 95f448162..fb52c09b1 100644 --- a/shared/runtime/pyexec.h +++ b/shared/runtime/pyexec.h @@ -37,6 +37,17 @@ extern pyexec_mode_kind_t pyexec_mode_kind; #define PYEXEC_FORCED_EXIT (0x100) +#if MICROPY_PYEXEC_ENABLE_EXIT_CODE_HANDLING +#define PYEXEC_NORMAL_EXIT (0) +#define PYEXEC_UNHANDLED_EXCEPTION (1) +#define PYEXEC_KEYBOARD_INTERRUPT (128 + 2) // same as SIG INT exit code +#define PYEXEC_ABORT (128 + 9) // same as SIG KILL exit code +#else +#define PYEXEC_NORMAL_EXIT (1) +#define PYEXEC_UNHANDLED_EXCEPTION (0) +#define PYEXEC_ABORT PYEXEC_FORCED_EXIT +#endif + int pyexec_raw_repl(void); int pyexec_friendly_repl(void); int pyexec_file(const char *filename); |
