8000 rgbmatrix: recover gracefully from allocation errors · dastels/circuitpython@2f120c7 · GitHub
[go: up one dir, main page]

Skip to content

Commit 2f120c7

Browse files
committed
rgbmatrix: recover gracefully from allocation errors
e.g., allocating a 192x32x6bpp matrix would be enough to trigger this reliably on a Metro M4 Express using the "memory hogging" layout. Allocating 64x32x6bpp could trigger it, but somewhat unreliably. There are several things going on here: * we make the failing call with interrupts off * we were throwing an exception with interrupts off * protomatter failed badly in _PM_free when it was partially-initialized Incorporate the fix from protomatter, switch to a non-throwing malloc variant, and ensure that interrupts get turned back on. This decreases the quality of the MemoryError (it cannot report the size of the failed allocation) but allows CircuitPython to survive, rather than faulting.
1 parent 9bd2a61 commit 2f120c7

File tree

3 files changed

+13
-8
lines changed

3 files changed

+13
-8
lines changed

lib/protomatter

Submodule protomatter updated 1 file

shared-module/rgbmatrix/RGBMatrix.c

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@ void common_hal_rgbmatrix_rgbmatrix_reconstruct(rgbmatrix_rgbmatrix_obj_t* self,
8989
self->bufinfo.typecode = 'H' | MP_OBJ_ARRAY_TYPECODE_FLAG_RW;
9090
}
9191

92+
memset(&self->core, 0, sizeof(self->core));
9293
ProtomatterStatus stat = _PM_init(&self->core,
9394
self->width, self->bit_depth,
9495
self->rgb_count/6, self->rgb_pins,
@@ -101,14 +102,17 @@ void common_hal_rgbmatrix_rgbmatrix_reconstruct(rgbmatrix_rgbmatrix_obj_t* self,
101102
common_hal_mcu_disable_interrupts();
102103
common_hal_rgbmatrix_timer_enable(self->timer);
103104
stat = _PM_begin(&self->core);
104-
_PM_convert_565(&self->core, self->bufinfo.buf, self->width);
105+
106+
if (stat == PROTOMATTER_OK) {
107+
_PM_convert_565(&self->core, self->bufinfo.buf, self->width);
108+
}
105109
common_hal_mcu_enable_interrupts();
106-
_PM_swapbuffer_maybe(&self->core);
110+
if (stat == PROTOMATTER_OK) {
111+
_PM_swapbuffer_maybe(&self->core);
112+
}
107113
}
108114

109115
if (stat != PROTOMATTER_OK) {
110-
// XXX this deinit() actually makes crashy-crashy
111-
// can trigger it by sending inappropriate pins
112116
common_hal_rgbmatrix_rgbmatrix_deinit(self);
113117
switch (stat) {
114118
case PROTOMATTER_ERR_PINS:
@@ -117,7 +121,9 @@ void common_hal_rgbmatrix_rgbmatrix_reconstruct(rgbmatrix_rgbmatrix_obj_t* self,
117121
case PROTOMATTER_ERR_ARG:
118122
mp_raise_ValueError(translate("Invalid argument"));
119123
break;
120-
case PROTOMATTER_ERR_MALLOC: /// should have already been signaled as NLR
124+
case PROTOMATTER_ERR_MALLOC:
125+
mp_raise_msg(&mp_type_MemoryError, NULL);
126+
break;
121127
default:
122128
mp_raise_msg_varg(&mp_type_RuntimeError,
123129
translate("Internal error #%d"), (int)stat);
@@ -126,7 +132,6 @@ void common_hal_rgbmatrix_rgbmatrix_reconstruct(rgbmatrix_rgbmatrix_obj_t* self,
126132
}
127133

128134
self->paused = 0;
129-
130135
}
131136

132137
STATIC void free_pin(uint8_t *pin) {

shared-module/rgbmatrix/allocator.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111

1212
static inline void *_PM_allocator_impl(size_t sz) {
1313
if (gc_alloc_possible()) {
14-
return m_malloc(sz + sizeof(void*), true);
14+
return m_malloc_maybe(sz + sizeof(void*), true);
1515
} else {
1616
supervisor_allocation *allocation = allocate_memory(align32_size(sz), false);
1717
return allocation ? allocation->ptr : NULL;

0 commit comments

Comments
 (0)
0