Commit 1c9210bc authored by Paul Sokolovsky's avatar Paul Sokolovsky
Browse files

unix/unix_mphal: Raise KeyboardInterrupt straight from signal handler.

POSIX doesn't guarantee something like that to work, but it works on any
system with careful signal implementation. Roughly, the requirement is
that signal handler is executed in the context of the process, its main
thread, etc. This is true for Linux. Also tested to work without issues
on MacOSX.
parent e9751d2a
......@@ -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)
......
......@@ -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;
......
......@@ -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
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment