summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--py/mpconfig.h10
-rw-r--r--shared/runtime/pyexec.c42
-rw-r--r--shared/runtime/pyexec.h11
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);