Skip to content

Commit ed5c0bd

Browse files
committed
rgbmatrix: Avoid leaving an incompletely configured display bus
I did not reproduce the exact problem reported; however, I reproduced that a failure to construct an RGBMatrix object would leave CircuitPython in an inconsistent state with a display bus registered but not working: ```py >>> import rgbmatrix, board; rgbmatrix.RGBMatrix(width=64, bit_depth=1, rgb_pins=[], addr_pins=[], clock_pin=board.A0, latch_pin=board.A1, output_enable_pin=board.A2) Traceback (most recent call last): File "<stdin>", line 1, in <module> ValueError: The length of rgb_pins must be 6, 12, 18, 24, or 30 >>> import rgbmatrix, board; rgbmatrix.RGBMatrix(width=64, bit_depth=1, rgb_pins=[], addr_pins=[], clock_pin=board.A0, latch_pin=board.A1, output_enable_pin=board.A2) Traceback (most recent call last): File "<stdin>", line 1, in <module> RuntimeError: Too many display busses; forgot displayio.release_displays() ? ``` After the fix the second call also results in a ValueError, not a RuntimeError, which is correct. Closes #9674
1 parent 407a31f commit ed5c0bd

File tree

1 file changed

+17
-1
lines changed

1 file changed

+17
-1
lines changed

shared-bindings/rgbmatrix/RGBMatrix.c

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,16 @@ static void preflight_pins_or_throw(uint8_t clock_pin, uint8_t *rgb_pins, uint8_
116116
#endif
117117
}
118118

119+
typedef struct {
120+
nlr_jump_callback_node_t callback;
121+
mp_obj_base_t *base_ptr;
122+
} nlr_jump_callback_node_clear_displaybus_t;
123+
124+
static void clear_display_bus(void *node_in) {
125+
nlr_jump_callback_node_clear_displaybus_t *node = node_in;
126+
node->base_ptr->type = &mp_type_NoneType;
127+
}
128+
119129
//| def __init__(
120130
//| self,
121131
//| *,
@@ -217,6 +227,13 @@ static mp_obj_t rgbmatrix_rgbmatrix_make_new(const mp_obj_type_t *type, size_t n
217227
rgbmatrix_rgbmatrix_obj_t *self = &allocate_display_bus_or_raise()->rgbmatrix;
218228
self->base.type = &rgbmatrix_RGBMatrix_type;
219229

230+
// If an exception is thrown, ensure the display bus object's type is set
231+
// back to the uninitialized/deinitialied type. **note that all other resource
232+
// deallocations must be handled by the shared-module code**
233+
nlr_jump_callback_node_clear_displaybus_t node;
234+
node.base_ptr = &self->base;
235+
nlr_push_jump_callback(&node.callback, clear_display_bus);
236+
220237
uint8_t rgb_count, addr_count;
221238
uint8_t rgb_pins[MP_ARRAY_SIZE(self->rgb_pins)];
222239
uint8_t addr_pins[MP_ARRAY_SIZE(self->addr_pins)];
@@ -254,7 +271,6 @@ static mp_obj_t rgbmatrix_rgbmatrix_make_new(const mp_obj_type_t *type, size_t n
254271
clock_pin, latch_pin, output_enable_pin,
255272
args[ARG_doublebuffer].u_bool,
256273
args[ARG_framebuffer].u_obj, tile, args[ARG_serpentine].u_bool, NULL);
257-
258274
claim_and_never_reset_pins(args[ARG_rgb_list].u_obj);
259275
claim_and_never_reset_pins(args[ARG_addr_list].u_obj);
260276
claim_and_never_reset_pin(args[ARG_clock_pin].u_obj);

0 commit comments

Comments
 (0)