From f8a9e11ff4f42620bbe6e678f009bdadcb4ac542 Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Sun, 23 Aug 2020 08:46:42 -0500 Subject: [PATCH 1/4] WIP supervisor: check for interrupt during rx_chr --- supervisor/shared/micropython.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/supervisor/shared/micropython.c b/supervisor/shared/micropython.c index 245db11d42..cd9485f8c0 100644 --- a/supervisor/shared/micropython.c +++ b/supervisor/shared/micropython.c @@ -29,14 +29,32 @@ #include "supervisor/serial.h" #include "lib/oofatfs/ff.h" #include "py/mpconfig.h" +#include "py/mpstate.h" #include "supervisor/shared/status_leds.h" +#if CIRCUITPY_WATCHDOG +#include "shared-bindings/watchdog/__init__.h" +#define WATCHDOG_EXCEPTION_CHECK() (MP_STATE_VM(mp_pending_exception) == &mp_watchdog_timeout_exception) +#else +#define WATCHDOG_EXCEPTION_CHECK() 0 +#endif + int mp_hal_stdin_rx_chr(void) { for (;;) { #ifdef MICROPY_VM_HOOK_LOOP MICROPY_VM_HOOK_LOOP #endif + // Check to see if we've been CTRL-Ced by autoreload or the user. + if (MP_STATE_VM(mp_pending_exception) == MP_OBJ_FROM_PTR(&MP_STATE_VM(mp_kbd_exception))) { + // clear exception and generate stacktrace + MP_STATE_VM(mp_pending_exception) = MP_OBJ_NULL; + nlr_raise(&MP_STATE_VM(mp_kbd_exception)); + } + if (MP_STATE_VM(mp_pending_exception) == MP_OBJ_FROM_PTR(&MP_STATE_VM(mp_reload_exception)) || WATCHDOG_EXCEPTION_CHECK()) { + // stop reading immediately + return EOF; + } if (serial_bytes_available()) { toggle_rx_led(); return serial_read(); From 1033e89561d6535f32aa4cfd3541ffd9683a1123 Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Sun, 23 Aug 2020 09:03:34 -0500 Subject: [PATCH 2/4] supervisor: use mp_handle_pending to check for exceptions --- supervisor/shared/micropython.c | 12 ++---------- supervisor/shared/tick.c | 13 ++----------- 2 files changed, 4 insertions(+), 21 deletions(-) diff --git a/supervisor/shared/micropython.c b/supervisor/shared/micropython.c index cd9485f8c0..bbc4807f97 100644 --- a/supervisor/shared/micropython.c +++ b/supervisor/shared/micropython.c @@ -30,6 +30,7 @@ #include "lib/oofatfs/ff.h" #include "py/mpconfig.h" #include "py/mpstate.h" +#include "py/runtime.h" #include "supervisor/shared/status_leds.h" @@ -45,16 +46,7 @@ int mp_hal_stdin_rx_chr(void) { #ifdef MICROPY_VM_HOOK_LOOP MICROPY_VM_HOOK_LOOP #endif - // Check to see if we've been CTRL-Ced by autoreload or the user. - if (MP_STATE_VM(mp_pending_exception) == MP_OBJ_FROM_PTR(&MP_STATE_VM(mp_kbd_exception))) { - // clear exception and generate stacktrace - MP_STATE_VM(mp_pending_exception) = MP_OBJ_NULL; - nlr_raise(&MP_STATE_VM(mp_kbd_exception)); - } - if (MP_STATE_VM(mp_pending_exception) == MP_OBJ_FROM_PTR(&MP_STATE_VM(mp_reload_exception)) || WATCHDOG_EXCEPTION_CHECK()) { - // stop reading immediately - return EOF; - } + mp_handle_pending(); if (serial_bytes_available()) { toggle_rx_led(); return serial_read(); diff --git a/supervisor/shared/tick.c b/supervisor/shared/tick.c index 4af59f78e3..f26e1e79d1 100644 --- a/supervisor/shared/tick.c +++ b/supervisor/shared/tick.c @@ -27,6 +27,7 @@ #include "supervisor/shared/tick.h" #include "py/mpstate.h" +#include "py/runtime.h" #include "supervisor/linker.h" #include "supervisor/filesystem.h" #include "supervisor/background_callback.h" @@ -149,17 +150,7 @@ void mp_hal_delay_ms(mp_uint_t delay) { while (remaining > 0) { RUN_BACKGROUND_TASKS; // Check to see if we've been CTRL-Ced by autoreload or the user. - if(MP_STATE_VM(mp_pending_exception) == MP_OBJ_FROM_PTR(&MP_STATE_VM(mp_kbd_exception))) - { - // clear exception and generate stacktrace - MP_STATE_VM(mp_pending_exception) = MP_OBJ_NULL; - nlr_raise(&MP_STATE_VM(mp_kbd_exception)); - } - if( MP_STATE_VM(mp_pending_exception) == MP_OBJ_FROM_PTR(&MP_STATE_VM(mp_reload_exception)) || - WATCHDOG_EXCEPTION_CHECK()) { - // stop sleeping immediately - break; - } + mp_handle_pending(); remaining = end_tick - port_get_raw_ticks(NULL); // We break a bit early so we don't risk setting the alarm before the time when we call // sleep. From e9bc8e892b5ccc88782d8aaf08868b0094eae414 Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Tue, 25 Aug 2020 11:45:00 -0500 Subject: [PATCH 3/4] pyexec: Handle a ctrl-c that comes in "very late" In relatively unusual circumstances, such as entering `l = 17 ** 17777` at the REPL, you could hit ctrl-c, but not get KeyboardInterrupt. This can lead to a condition where the display would stop updating (#2689). --- lib/utils/pyexec.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/utils/pyexec.c b/lib/utils/pyexec.c index 8e99bc2099..378fb6267d 100755 --- a/lib/utils/pyexec.c +++ b/lib/utils/pyexec.c @@ -113,6 +113,8 @@ STATIC int parse_compile_execute(const void *source, mp_parse_input_kind_t input start = mp_hal_ticks_ms(); mp_call_function_0(module_fun); mp_hal_set_interrupt_char(-1); // disable interrupt + // Handle any ctrl-c interrupt that arrived just in time + mp_handle_pending(); nlr_pop(); ret = 0; if (exec_flags & EXEC_FLAG_PRINT_EOF) { From c0753c1afb09dab873da02e6f98a492cb913f0e9 Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Tue, 25 Aug 2020 11:46:49 -0500 Subject: [PATCH 4/4] mp_obj_print_helper: Handle a ctrl-c that comes in during printing In #2689, hitting ctrl-c during the printing of an object with a lot of sub-objects could cause the screen to stop updating (without showing a KeyboardInterrupt). This makes the printing of such objects acutally interruptable, and also correctly handles the KeyboardInterrupt: ``` >>> l = ["a" * 100] * 200 >>> l ['aaaaaaaaaaaaaaaaaaaaaa...aaaaaaaaaaa', Traceback (most recent call last): File "", line 1, in KeyboardInterrupt: >>> ``` --- py/obj.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/py/obj.c b/py/obj.c index 0cff2f1a4b..9dc0cf4749 100644 --- a/py/obj.c +++ b/py/obj.c @@ -67,6 +67,8 @@ void mp_obj_print_helper(const mp_print_t *print, mp_obj_t o_in, mp_print_kind_t #ifdef RUN_BACKGROUND_TASKS RUN_BACKGROUND_TASKS; #endif + mp_handle_pending(); + #ifndef NDEBUG if (o_in == MP_OBJ_NULL) { mp_print_str(print, "(nil)");