diff options
author | Damien George <damien.p.george@gmail.com> | 2014-10-25 18:19:55 +0100 |
---|---|---|
committer | Damien George <damien.p.george@gmail.com> | 2014-10-25 23:37:57 +0100 |
commit | 124df6f8d07b53542b6960dbeea9b63bff469a67 (patch) | |
tree | 39ea11d0bed72ed828c406d2b4a8fc069b00ca4e /unix/main.c | |
parent | d7353fe6fe9c9d421ef045c0eea8d4591710e1ba (diff) | |
download | micropython-124df6f8d07b53542b6960dbeea9b63bff469a67.tar.gz micropython-124df6f8d07b53542b6960dbeea9b63bff469a67.zip |
py: Add mp_pending_exception global variable, for VM soft interrupt.
This allows to implement KeyboardInterrupt on unix, and a much safer
ctrl-C in stmhal port. First ctrl-C is a soft one, with hope that VM
will notice it; second ctrl-C is a hard one that kills anything (for
both unix and stmhal).
One needs to check for a pending exception in the VM only for jump
opcodes. Others can't produce an infinite loop (infinite recursion is
caught by stack check).
Diffstat (limited to 'unix/main.c')
-rw-r--r-- | unix/main.c | 27 |
1 files changed, 27 insertions, 0 deletions
diff --git a/unix/main.c b/unix/main.c index a8de9fdee3..44542af51b 100644 --- a/unix/main.c +++ b/unix/main.c @@ -34,6 +34,7 @@ #include <sys/stat.h> #include <sys/types.h> #include <errno.h> +#include <signal.h> #include "mpconfig.h" #include "nlr.h" @@ -64,6 +65,20 @@ mp_uint_t mp_verbose_flag = 0; long heap_size = 128*1024 * (sizeof(mp_uint_t) / 4); #endif +STATIC mp_obj_t keyboard_interrupt_obj; + +STATIC void sighandler(int signum) { + if (signum == SIGINT) { + mp_obj_exception_clear_traceback(keyboard_interrupt_obj); + mp_pending_exception = keyboard_interrupt_obj; + // disable our handler so next we really die + struct sigaction sa; + sa.sa_handler = SIG_DFL; + sigemptyset(&sa.sa_mask); + sigaction(SIGINT, &sa, NULL); + } +} + #define FORCED_EXIT (0x100) // returns standard error codes: 0 for success, 1 for all other errors // if FORCED_EXIT bit is set then script raised SystemExit and the @@ -119,14 +134,23 @@ STATIC int execute_from_lexer(mp_lexer_t *lex, mp_parse_input_kind_t input_kind, return 0; } + // enable signal handler + struct sigaction sa; + sa.sa_handler = sighandler; + sigemptyset(&sa.sa_mask); + sigaction(SIGINT, &sa, NULL); + sa.sa_handler = SIG_DFL; + // execute it nlr_buf_t nlr; if (nlr_push(&nlr) == 0) { mp_call_function_0(module_fun); + sigaction(SIGINT, &sa, NULL); nlr_pop(); return 0; } else { // uncaught exception + sigaction(SIGINT, &sa, NULL); // check for SystemExit mp_obj_t exc = (mp_obj_t)nlr.ret_val; if (mp_obj_is_subclass_fast(mp_obj_get_type(exc), &mp_type_SystemExit)) { @@ -305,6 +329,9 @@ int main(int argc, char **argv) { mp_init(); + // create keyboard interrupt object + keyboard_interrupt_obj = mp_obj_new_exception(&mp_type_KeyboardInterrupt); + char *home = getenv("HOME"); char *path = getenv("MICROPYPATH"); if (path == NULL) { |