diff --git a/ports/unix/main.c b/ports/unix/main.c index 55fd8406ba..ecc6924494 100644 --- a/ports/unix/main.c +++ b/ports/unix/main.c @@ -242,6 +242,17 @@ static int do_repl(void) { } static inline int convert_pyexec_result(int ret) { + #if MICROPY_PYEXEC_ENABLE_EXIT_CODE_HANDLING + // With exit code handling enabled: + // pyexec returns exit code with PYEXEC_FORCED_EXIT flag set for SystemExit + // Unix port expects: 0 for success, non-zero for error/exit + if (ret & PYEXEC_FORCED_EXIT) { + // SystemExit: extract exit code from lower bits + return ret & 0xFF; + } + // Normal execution or exception: return as-is (0 for success, 1 for exception) + return ret; + #else // pyexec returns 1 for success, 0 for exception, PYEXEC_FORCED_EXIT for SystemExit // Convert to unix port's expected codes: 0 for success, 1 for exception, FORCED_EXIT|val for SystemExit if (ret == 1) { @@ -251,6 +262,7 @@ static inline int convert_pyexec_result(int ret) { } else { return 1; // exception } + #endif } static int do_file(const char *file) { diff --git a/ports/unix/mpconfigport.h b/ports/unix/mpconfigport.h index 562c93f99b..854da1dbd4 100644 --- a/ports/unix/mpconfigport.h +++ b/ports/unix/mpconfigport.h @@ -154,6 +154,9 @@ typedef long mp_off_t; // Enable support for compile-only mode. #define MICROPY_PYEXEC_COMPILE_ONLY (1) +// Enable handling of sys.exit() exit codes. +#define MICROPY_PYEXEC_ENABLE_EXIT_CODE_HANDLING (1) + #define MICROPY_PY_SOCKET_LISTEN_BACKLOG_DEFAULT (SOMAXCONN < 128 ? SOMAXCONN : 128) // Bare-metal ports don't have stderr. Printing debug to stderr may give tests diff --git a/ports/windows/mpconfigport.h b/ports/windows/mpconfigport.h index 24c54438e6..1edcd0eded 100644 --- a/ports/windows/mpconfigport.h +++ b/ports/windows/mpconfigport.h @@ -164,6 +164,9 @@ // Enable support for compile-only mode. #define MICROPY_PYEXEC_COMPILE_ONLY (1) +// Enable handling of sys.exit() exit codes. +#define MICROPY_PYEXEC_ENABLE_EXIT_CODE_HANDLING (1) + #define MICROPY_ERROR_REPORTING (MICROPY_ERROR_REPORTING_DETAILED) #define MICROPY_ERROR_PRINTER (&mp_stderr_print) #define MICROPY_WARNINGS (1) diff --git a/shared/runtime/pyexec.c b/shared/runtime/pyexec.c index d2a1403e38..428cc95b23 100644 --- a/shared/runtime/pyexec.c +++ b/shared/runtime/pyexec.c @@ -165,6 +165,7 @@ static int parse_compile_execute(const void *source, mp_parse_input_kind_t input #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 + // None is an exit value of 0; an int is its value; anything else is 1 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)) {