Skip to content

Commit c8072e4

Browse files
committed
py/scheduler: Schedule SystemExit or SystemAbort.
This implements mp_sched_system_exit_or_abort(), which can be used to schedule a SystemExit or SystemAbort on the main thread. This can be used by async sources to exit MicroPython if requested by a firmware process. Use abort=true if the MicroPython script must not be able to catch it, not even with a bare except. The implementation is similar to mp_sched_keyboard_interrupt(). Signed-off-by: Laurens Valk <laurens@pybricks.com>
1 parent e40c35d commit c8072e4

File tree

6 files changed

+32
-3
lines changed

6 files changed

+32
-3
lines changed

py/mpconfig.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -659,7 +659,8 @@
659659
#endif
660660

661661
// Whether to provide the SystemAbort exception, used to exit MicroPython
662-
// even if user code catches all exceptions.
662+
// even if user code catches all exceptions. This also provides
663+
// mp_sched_system_exit_or_abort() to schedule the mp_system_exception object.
663664
#ifndef MICROPY_ENABLE_SYSTEM_ABORT
664665
#define MICROPY_ENABLE_SYSTEM_ABORT (0)
665666
#endif

py/mpstate.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,11 @@ typedef struct _mp_state_vm_t {
165165
mp_obj_exception_t mp_kbd_exception;
166166
#endif
167167

168+
#if MICROPY_ENABLE_SYSTEM_ABORT
169+
// exception object of type SystemExit or SystemAbort
170+
mp_obj_exception_t mp_system_exception;
171+
#endif
172+
168173
// dictionary with loaded modules (may be exposed as sys.modules)
169174
mp_obj_dict_t mp_loaded_modules_dict;
170175

py/objexcept.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -377,8 +377,9 @@ MP_DEFINE_EXCEPTION(Exception, BaseException)
377377
*/
378378

379379
#if MICROPY_ENABLE_SYSTEM_ABORT
380-
// Exception that can't be raised or caught by user code, not even with a
381-
// bare except. Can be used to force MicroPython to exit from C code.
380+
// Exception that can't be raised or caught by user code, not even with a bare
381+
// except. Do not raise directly but use mp_sched_system_exit_or_abort(true) to
382+
// schedule it on the main thread.
382383
MP_DEFINE_EXCEPTION(SystemAbort, BaseException)
383384
#endif
384385

py/runtime.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,14 @@ void mp_init(void) {
9595
MP_STATE_VM(mp_kbd_exception).args = (mp_obj_tuple_t *)&mp_const_empty_tuple_obj;
9696
#endif
9797

98+
#if MICROPY_ENABLE_SYSTEM_ABORT
99+
// initialise the exception object for raising SystemExit or SystemAbort
100+
MP_STATE_VM(mp_system_exception).traceback_alloc = 0;
101+
MP_STATE_VM(mp_system_exception).traceback_len = 0;
102+
MP_STATE_VM(mp_system_exception).traceback_data = NULL;
103+
MP_STATE_VM(mp_system_exception).args = (mp_obj_tuple_t *)&mp_const_empty_tuple_obj;
104+
#endif
105+
98106
#if MICROPY_ENABLE_COMPILER
99107
// optimization disabled by default
100108
MP_STATE_VM(mp_optimise_value) = 0;

py/runtime.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,9 @@ void mp_deinit(void);
7575

7676
void mp_sched_exception(mp_obj_t exc);
7777
void mp_sched_keyboard_interrupt(void);
78+
#if MICROPY_ENABLE_SYSTEM_ABORT
79+
void mp_sched_system_exit_or_abort(bool abort);
80+
#endif
7881
void mp_handle_pending(bool raise_exc);
7982

8083
#if MICROPY_ENABLE_SCHEDULER

py/scheduler.c

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,17 @@ void MICROPY_WRAP_MP_SCHED_KEYBOARD_INTERRUPT(mp_sched_keyboard_interrupt)(void)
5151
}
5252
#endif
5353

54+
#if MICROPY_ENABLE_SYSTEM_ABORT
55+
// Schedules SystemExit or SystemAbort on the main thread. Can be used by
56+
// async sources to exit MicroPython. Use abort=true if the MicroPython script
57+
// must not be able to catch it, not even with a bare except.
58+
void MICROPY_WRAP_MP_SCHED_EXCEPTION(mp_sched_system_exit_or_abort)(bool abort) {
59+
MP_STATE_VM(mp_system_exception).base.type = abort ?
60+
&mp_type_SystemAbort : &mp_type_SystemExit;
61+
mp_sched_exception(MP_OBJ_FROM_PTR(&MP_STATE_VM(mp_system_exception)));
62+
}
63+
#endif
64+
5465
#if MICROPY_ENABLE_SCHEDULER
5566

5667
#define IDX_MASK(i) ((i) & (MICROPY_SCHEDULER_DEPTH - 1))

0 commit comments

Comments
 (0)