Skip to content

Commit 259d9b6

Browse files
dlechdpgeorge
authored andcommitted
py/mpstate: Schedule KeyboardInterrupt on main thread.
This introduces a new macro to get the main thread and uses it to ensure that asynchronous exceptions such as KeyboardInterrupt (CTRL+C) are only scheduled on the main thread. This is more deterministic than being scheduled on a random thread and is more in line with CPython that only allow signal handlers to run on the main thread. Fixes issue micropython#7026. Signed-off-by: David Lechner <[email protected]>
1 parent ca920f7 commit 259d9b6

File tree

6 files changed

+10
-7
lines changed

6 files changed

+10
-7
lines changed

ports/pic16bit/board.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,7 @@ int switch_get(int sw) {
140140
// TODO need an irq
141141
void uart_rx_irq(void) {
142142
if (c == interrupt_char) {
143-
MP_STATE_THREAD(mp_pending_exception) = MP_STATE_PORT(keyboard_interrupt_obj);
143+
MP_STATE_MAIN_THREAD(mp_pending_exception) = MP_STATE_PORT(keyboard_interrupt_obj);
144144
}
145145
}
146146
*/

ports/stm32/pendsv.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,10 +60,10 @@ void pendsv_init(void) {
6060
// the given exception object using nlr_jump in the context of the top-level
6161
// thread.
6262
void pendsv_kbd_intr(void) {
63-
if (MP_STATE_THREAD(mp_pending_exception) == MP_OBJ_NULL) {
63+
if (MP_STATE_MAIN_THREAD(mp_pending_exception) == MP_OBJ_NULL) {
6464
mp_sched_keyboard_interrupt();
6565
} else {
66-
MP_STATE_THREAD(mp_pending_exception) = MP_OBJ_NULL;
66+
MP_STATE_MAIN_THREAD(mp_pending_exception) = MP_OBJ_NULL;
6767
pendsv_object = &MP_STATE_VM(mp_kbd_exception);
6868
SCB->ICSR = SCB_ICSR_PENDSVSET_Msk;
6969
}

ports/unix/unix_mphal.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ STATIC void sighandler(int signum) {
5454
sigprocmask(SIG_SETMASK, &mask, NULL);
5555
nlr_raise(MP_OBJ_FROM_PTR(&MP_STATE_VM(mp_kbd_exception)));
5656
#else
57-
if (MP_STATE_THREAD(mp_pending_exception) == MP_OBJ_FROM_PTR(&MP_STATE_VM(mp_kbd_exception))) {
57+
if (MP_STATE_MAIN_THREAD(mp_pending_exception) == MP_OBJ_FROM_PTR(&MP_STATE_VM(mp_kbd_exception))) {
5858
// this is the second time we are called, so die straight away
5959
exit(1);
6060
}

ports/windows/windows_mphal.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ void mp_hal_stdio_mode_orig(void) {
8080
// the thread created for handling it might not be running yet so we'd miss the notification.
8181
BOOL WINAPI console_sighandler(DWORD evt) {
8282
if (evt == CTRL_C_EVENT) {
83-
if (MP_STATE_THREAD(mp_pending_exception) == MP_OBJ_FROM_PTR(&MP_STATE_VM(mp_kbd_exception))) {
83+
if (MP_STATE_MAIN_THREAD(mp_pending_exception) == MP_OBJ_FROM_PTR(&MP_STATE_VM(mp_kbd_exception))) {
8484
// this is the second time we are called, so die straight away
8585
exit(1);
8686
}

py/mpstate.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -285,12 +285,13 @@ extern mp_state_ctx_t mp_state_ctx;
285285

286286
#define MP_STATE_VM(x) (mp_state_ctx.vm.x)
287287
#define MP_STATE_MEM(x) (mp_state_ctx.mem.x)
288+
#define MP_STATE_MAIN_THREAD(x) (mp_state_ctx.thread.x)
288289

289290
#if MICROPY_PY_THREAD
290291
extern mp_state_thread_t *mp_thread_get_state(void);
291292
#define MP_STATE_THREAD(x) (mp_thread_get_state()->x)
292293
#else
293-
#define MP_STATE_THREAD(x) (mp_state_ctx.thread.x)
294+
#define MP_STATE_THREAD(x) MP_STATE_MAIN_THREAD(x)
294295
#endif
295296

296297
#endif // MICROPY_INCLUDED_PY_MPSTATE_H

py/scheduler.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,10 @@
2828

2929
#include "py/runtime.h"
3030

31+
// Schedules an exception on the main thread (for exceptions "thrown" by async
32+
// sources such as interrupts and UNIX signal handlers).
3133
void MICROPY_WRAP_MP_SCHED_EXCEPTION(mp_sched_exception)(mp_obj_t exc) {
32-
MP_STATE_THREAD(mp_pending_exception) = exc;
34+
MP_STATE_MAIN_THREAD(mp_pending_exception) = exc;
3335
#if MICROPY_ENABLE_SCHEDULER
3436
if (MP_STATE_VM(sched_state) == MP_SCHED_IDLE) {
3537
MP_STATE_VM(sched_state) = MP_SCHED_PENDING;

0 commit comments

Comments
 (0)