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