Harden DMA buffer allocation against transient heap exhaustion#212
Merged
Conversation
Follow-up to m5stack#211: apply the same null guard to the three getDMABuffer() call sites in writeImage(), via a shared get_dma_buffer_checked() helper with edge-triggered logging.
- FlipBuffer/SimpleBuffer: when shrinking, never discard a buffer that still satisfies the request; allocate the smaller one first and keep the old one on failure. Add reserve() to pre-size buffers with a shrink floor. - IBus: add reserveDMABuffer(), implemented by esp32-family buses. - Panel_Device: reserve one line of pixels at init so steady-state draws never reallocate; add get_dma_buffer_checked() helper with edge-triggered logging. - Guard the remaining panel-layer getDMABuffer() call sites (Panel_LCD, Panel_M5HDMI, Panel_ED2208, Panel_M5UnitLCD, writeImageARGB) and migrate Panel_AMOLED to the shared helper.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Follow-up to #211, extending the null-DMA-buffer protection from the AMOLED framebuffer flush to the whole library.
Problem
IBus::getDMABuffer()returnsnullptrwhen the DMA-capable internal heap is transiently exhausted. #211 guarded one call site, but the same unchecked pattern existed across the panel layer (Panel_LCD,Panel_M5HDMI,Panel_ED2208,Panel_M5UnitLCD,Panel_Device::writeImageARGB), and the underlying buffer classes had a self-inflicted failure mode: on a size change they freed the old buffer before allocating the new one, so a buffer that could still satisfy the request was lost when the allocation failed.SimpleBuffer(used byBus_I2C) reallocated on any size change, not just growth.Changes
Buffer layer (
platforms/common.hpp)FlipBuffer/SimpleBuffer: shrinking now allocates the smaller buffer first and keeps the old one on failure; a buffer that already satisfies the request is never discarded.reserve(): pre-allocates and sets a floor below whichgetBuffer()never shrinks.Bus layer
IBus::reserveDMABuffer()(default no-op), implemented by the esp32-family buses.Panel layer
Panel_Device::init()reserves one line of pixels (covering both rotations), so steady-state draws never reallocate mid-draw.Panel_Device::get_dma_buffer_checked()with edge-triggeredESP_LOGW/ESP_LOGI(no per-frame spam); all livegetDMABuffer()call sites in the panel layer now use it and skip the write on failure (Panel_ED2208breaks to its transaction/CS cleanup instead of returning).Panel_AMOLEDmigrates its fix: guard against null DMA buffer in Panel_AMOLED_Framebuffer::display() #211-era local helper to the shared one.Behavior on exhaustion
Instead of a
StoreProhibitedpanic, the affected write is dropped (pixels skipped; the AMOLED framebuffer path retries via its dirty rectangle) and a single warning is logged until recovery.Notes