extmod/modbluetooth: Run BLE IRQ callback in protected NLR context.
The call to invoke_irq_handler_run() always needs to run in a protected NLR
context, to catch exceptions from the Python handler, and the m_new's (and
also mp_local_alloc when PYSTACK is enabled). With
MICROPY_PY_BLUETOOTH_USE_SYNC_EVENTS_WITH_INTERLOCK enabled there was
already an explicit nlr_push, and that is now used in all cases.
Without this change, on stm32 (for example), the callbacks from the BLE
stack to invoke_irq_handler() were made via static scheduled nodes which do
not have any NLR protection, and hence would lead to a hard fault (uncaught
NLR) if an exception was raised in the Python BLE IRQ handler. This was a
regression introduced by 8045ac07f5
, which is
fixed by this commit.
Signed-off-by: Damien George <damien@micropython.org>
This commit is contained in:
parent
db668742a5
commit
f2ad152e7e
|
@ -1143,10 +1143,6 @@ STATIC mp_obj_t invoke_irq_handler_run(uint16_t event,
|
||||||
const uint8_t *addr,
|
const uint8_t *addr,
|
||||||
const mp_obj_bluetooth_uuid_t *uuid,
|
const mp_obj_bluetooth_uuid_t *uuid,
|
||||||
const uint8_t **data, uint16_t *data_len, size_t n_data) {
|
const uint8_t **data, uint16_t *data_len, size_t n_data) {
|
||||||
mp_obj_bluetooth_ble_t *o = MP_OBJ_TO_PTR(MP_STATE_VM(bluetooth));
|
|
||||||
if (o->irq_handler == mp_const_none) {
|
|
||||||
return mp_const_none;
|
|
||||||
}
|
|
||||||
|
|
||||||
mp_obj_array_t mv_addr;
|
mp_obj_array_t mv_addr;
|
||||||
mp_obj_array_t mv_data[2];
|
mp_obj_array_t mv_data[2];
|
||||||
|
@ -1210,6 +1206,7 @@ STATIC mp_obj_t invoke_irq_handler_run(uint16_t event,
|
||||||
|
|
||||||
assert(data_tuple->len <= MICROPY_PY_BLUETOOTH_MAX_EVENT_DATA_TUPLE_LEN);
|
assert(data_tuple->len <= MICROPY_PY_BLUETOOTH_MAX_EVENT_DATA_TUPLE_LEN);
|
||||||
|
|
||||||
|
mp_obj_bluetooth_ble_t *o = MP_OBJ_TO_PTR(MP_STATE_VM(bluetooth));
|
||||||
mp_obj_t result = mp_call_function_2(o->irq_handler, MP_OBJ_NEW_SMALL_INT(event), MP_OBJ_FROM_PTR(data_tuple));
|
mp_obj_t result = mp_call_function_2(o->irq_handler, MP_OBJ_NEW_SMALL_INT(event), MP_OBJ_FROM_PTR(data_tuple));
|
||||||
|
|
||||||
#if MICROPY_PY_BLUETOOTH_USE_GATTC_EVENT_DATA_REASSEMBLY
|
#if MICROPY_PY_BLUETOOTH_USE_GATTC_EVENT_DATA_REASSEMBLY
|
||||||
|
@ -1223,6 +1220,34 @@ STATIC mp_obj_t invoke_irq_handler_run(uint16_t event,
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
STATIC mp_obj_t invoke_irq_handler_run_protected(uint16_t event,
|
||||||
|
const mp_int_t *numeric, size_t n_unsigned, size_t n_signed,
|
||||||
|
const uint8_t *addr,
|
||||||
|
const mp_obj_bluetooth_uuid_t *uuid,
|
||||||
|
const uint8_t **data, uint16_t *data_len, size_t n_data) {
|
||||||
|
|
||||||
|
mp_obj_bluetooth_ble_t *o = MP_OBJ_TO_PTR(MP_STATE_VM(bluetooth));
|
||||||
|
if (o->irq_handler == mp_const_none) {
|
||||||
|
return mp_const_none;
|
||||||
|
}
|
||||||
|
|
||||||
|
mp_obj_t result = mp_const_none;
|
||||||
|
nlr_buf_t nlr;
|
||||||
|
if (nlr_push(&nlr) == 0) {
|
||||||
|
result = invoke_irq_handler_run(event, numeric, n_unsigned, n_signed, addr, uuid, data, data_len, n_data);
|
||||||
|
nlr_pop();
|
||||||
|
} else {
|
||||||
|
// Uncaught exception, print it out.
|
||||||
|
mp_printf(MICROPY_ERROR_PRINTER, "Unhandled exception in IRQ callback handler\n");
|
||||||
|
mp_obj_print_exception(MICROPY_ERROR_PRINTER, MP_OBJ_FROM_PTR(nlr.ret_val));
|
||||||
|
|
||||||
|
// Disable the BLE IRQ handler.
|
||||||
|
o->irq_handler = mp_const_none;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
#if MICROPY_PY_BLUETOOTH_USE_SYNC_EVENTS_WITH_INTERLOCK
|
#if MICROPY_PY_BLUETOOTH_USE_SYNC_EVENTS_WITH_INTERLOCK
|
||||||
|
|
||||||
// On some systems the BLE event callbacks may occur on a system thread which is not
|
// On some systems the BLE event callbacks may occur on a system thread which is not
|
||||||
|
@ -1256,19 +1281,9 @@ STATIC mp_obj_t invoke_irq_handler(uint16_t event,
|
||||||
MP_THREAD_GIL_ENTER();
|
MP_THREAD_GIL_ENTER();
|
||||||
}
|
}
|
||||||
|
|
||||||
mp_obj_t result = mp_const_none;
|
mp_sched_lock();
|
||||||
nlr_buf_t nlr;
|
mp_obj_t result = invoke_irq_handler_run_protected(event, numeric, n_unsigned, n_signed, addr, uuid, data, data_len, n_data);
|
||||||
if (nlr_push(&nlr) == 0) {
|
mp_sched_unlock();
|
||||||
mp_sched_lock();
|
|
||||||
result = invoke_irq_handler_run(event, numeric, n_unsigned, n_signed, addr, uuid, data, data_len, n_data);
|
|
||||||
mp_sched_unlock();
|
|
||||||
nlr_pop();
|
|
||||||
} else {
|
|
||||||
// Uncaught exception, print it out.
|
|
||||||
mp_sched_unlock();
|
|
||||||
mp_printf(MICROPY_ERROR_PRINTER, "Unhandled exception in IRQ callback handler\n");
|
|
||||||
mp_obj_print_exception(MICROPY_ERROR_PRINTER, MP_OBJ_FROM_PTR(nlr.ret_val));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ts_orig == NULL) {
|
if (ts_orig == NULL) {
|
||||||
MP_THREAD_GIL_EXIT();
|
MP_THREAD_GIL_EXIT();
|
||||||
|
@ -1288,7 +1303,7 @@ STATIC mp_obj_t invoke_irq_handler(uint16_t event,
|
||||||
const uint8_t *addr,
|
const uint8_t *addr,
|
||||||
const mp_obj_bluetooth_uuid_t *uuid,
|
const mp_obj_bluetooth_uuid_t *uuid,
|
||||||
const uint8_t **data, uint16_t *data_len, size_t n_data) {
|
const uint8_t **data, uint16_t *data_len, size_t n_data) {
|
||||||
return invoke_irq_handler_run(event, numeric, n_unsigned, n_signed, addr, uuid, data, data_len, n_data);
|
return invoke_irq_handler_run_protected(event, numeric, n_unsigned, n_signed, addr, uuid, data, data_len, n_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in New Issue