diff --git a/py/mpconfig.h b/py/mpconfig.h index 6de184a9c4835f8af57e6286c1e15b2a49d26984..5e717ad0f68b18b65661983d6986a6216dbc27af 100644 --- a/py/mpconfig.h +++ b/py/mpconfig.h @@ -371,6 +371,12 @@ # endif #endif +// Prefer to raise KeyboardInterrupt asynchronously (from signal or interrupt +// handler) - if supported by a particular port. +#ifndef MICROPY_ASYNC_KBD_INTR +#define MICROPY_ASYNC_KBD_INTR (0) +#endif + // Whether to include REPL helper function #ifndef MICROPY_HELPER_REPL #define MICROPY_HELPER_REPL (0) diff --git a/unix/mpconfigport.h b/unix/mpconfigport.h index a20f1c50940ef7eb77ae8c8cc9873cac671a7e7e..a74345817dc16ae65751fc8608b856a7a70d6965 100644 --- a/unix/mpconfigport.h +++ b/unix/mpconfigport.h @@ -128,6 +128,7 @@ #define MICROPY_ENABLE_EMERGENCY_EXCEPTION_BUF (1) #define MICROPY_EMERGENCY_EXCEPTION_BUF_SIZE (256) +#define MICROPY_ASYNC_KBD_INTR (1) extern const struct _mp_obj_module_t mp_module_machine; extern const struct _mp_obj_module_t mp_module_os; diff --git a/unix/unix_mphal.c b/unix/unix_mphal.c index dbb6fbcdd4374b59bea55bc553596839957c9749..8d3321ef66d163fb40b664cd98184566b8a4511e 100644 --- a/unix/unix_mphal.c +++ b/unix/unix_mphal.c @@ -37,12 +37,22 @@ STATIC void sighandler(int signum) { if (signum == SIGINT) { + #if MICROPY_ASYNC_KBD_INTR + mp_obj_exception_clear_traceback(MP_STATE_VM(keyboard_interrupt_obj)); + sigset_t mask; + sigemptyset(&mask); + // On entry to handler, its signal is blocked, and unblocked on + // normal exit. As we instead perform longjmp, unblock it manually. + sigprocmask(SIG_SETMASK, &mask, NULL); + nlr_raise(MP_STATE_VM(keyboard_interrupt_obj)); + #else if (MP_STATE_VM(mp_pending_exception) == MP_STATE_VM(keyboard_interrupt_obj)) { // this is the second time we are called, so die straight away exit(1); } mp_obj_exception_clear_traceback(MP_STATE_VM(keyboard_interrupt_obj)); MP_STATE_VM(mp_pending_exception) = MP_STATE_VM(keyboard_interrupt_obj); + #endif } } #endif