Skip to content

Conversation

Copilot
Copy link
Contributor

@Copilot Copilot AI commented Oct 2, 2025

Problem

Enabling 2D mode and setting a panel size larger than the number of configured LEDs causes the ESP to crash with heap corruption. The crash only occurs when LEDs are ON (not OFF).

From the crash logs and debug output, the issue manifests as:

CORRUPT HEAP: Bad head at 0x3ffd6158. Expected 0xabba1234 got 0x00000000
Guru Meditation Error: Core 0 panic'ed (LoadProhibited)

Root Cause

A race condition in the 2D configuration save process:

When saving 2D config in set.cpp, the following sequence occurs:

  1. strip.deserializeMap() is called, which calls setUpMatrix()
  2. setUpMatrix() suspends the service loop, updates Segment::maxWidth and Segment::maxHeight to the new panel dimensions, then immediately calls resume()
  3. The service loop can now run with NEW matrix dimensions but OLD segments
  4. Next line: strip.makeAutoSegments(true) recreates segments with correct dimensions
  5. If the new dimensions exceed the configured LED count, segments attempt to access pixels beyond the allocated buffer during step 3, causing out-of-bounds memory access and heap corruption

Solution

Defer resume() until after segments are recreated to ensure the service loop never runs with inconsistent state:

In wled00/FX_2Dfcn.cpp:

  • Removed resume() from setUpMatrix() success path
  • Added comment explaining callers must handle resume
  • Kept resume() in error path where resetSegments() creates valid state

In wled00/set.cpp:

  • Added resume() after both deserializeMap() and makeAutoSegments() complete

In wled00/wled.cpp:

  • Added resume() after segment operations in initialization paths

This ensures the strip service loop remains suspended during the entire critical section where matrix dimensions and segments are being updated.

Testing

  • ✅ All existing tests pass
  • ✅ Build completes successfully
  • ✅ All suspend/resume pairs verified to be balanced
  • ✅ Logic traced through complete 2D config save path

Impact

This is a minimal surgical fix that:

  • Changes only 3 files (5 lines added, 1 removed)
  • Preserves all existing functionality
  • Fixes the critical crash without introducing new complexity

Fixes the crash described in the issue where enabling 2D with larger panel size than LED count would cause heap corruption and device reboot.

Co-authored-by: @DedeHai

Original prompt

This section details on the original issue you should resolve

<issue_title>Saving 2D config with higher LED count than configured leads to crash</issue_title>
<issue_description>### What happened?

I think this was discussed on Discord. When enabling 2D before setting the right amount of LEDs in config WLED just crashes.
I did some investigation on this but was not able to find where exactly this happes

To Reproduce Bug

Enable 2D and set the panel size larger than the number of configured LEDs.

Expected Behavior

Save the 2D setting without crashing.

Install Method

Self-Compiled

What version of WLED?

0.16

Which microcontroller/board are you seeing the problem on?

ESP32-C3

Relevant log/trace output

Anything else?

No response

Code of Conduct

  • I agree to follow this project's Code of Conduct</issue_description>

<agent_instructions>#4808 does NOT fix this.
The crash does not happen if leds are turned off.
Very rarely, it does get to the point where it saves. If then changing back to 1D, it still crashes and does not save. Increasing _pixels[] buffer (4x the amount of LEDs so more than large enough) does not help at all so its not that.</agent_instructions>

Comments on the Issue (you are @copilot in this section)

@blazoncek As you marked it confirmed, can you provide a crash dump? @DedeHai sure. Apologies, I wanted to open this before I forget :)
Ada
Guru Meditation Error: Core  1 panic'ed (LoadProhibited). Exception was unhandled.

Core  1 register dump:
PC      : 0x40082ead  PS      : 0x00050032  A0      : 0x40087ca8  A1      : 0x3ffbf870  
=> 0x40082ead: i2s_ll_get_intr_status at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/hal/esp32/include/hal/i2s_ll.h:398
      (inlined by) i2s_intr_handler_default at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/driver/i2s.c:434
=> 0x40087ca8: _xt_medint2 at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/freertos/port/xtensa/xtensa_vectors.S:1203
A2      : 0x3ffd6a7c  A3      : 0x00000000  A4      : 0x80081b26  A5      : 0x4008f232  
=> 0x4008f232: _frxt_int_enter at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/freertos/port/xtensa/portasm.S:119
A6      : 0x00000000  A7      : 0xffffff80  A8      : 0x00000001  A9      : 0x00000000
A10     : 0x00000000  A11     : 0x00000000  A12     : 0x800f22b4  A13     : 0x3ffcbf50
A14     : 0x3ffd5078  A15     : 0x00000000  SAR     : 0x0000000a  EXCCAUSE: 0x0000001c
EXCVADDR: 0x00000010  LBEG    : 0x40087705  LEND    : 0x4008770d  LCOUNT  : 0x00000027
=> 0x40087705: esp_timer_impl_get_counter_reg at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/esp_timer/src/esp_timer_impl_lac.c:118 (discriminator 2)
=> 0x4008770d: esp_timer_impl_get_counter_reg at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/esp_timer/src/esp_timer_impl_lac.c:128 (discriminator 1)


Backtrace: 0x40082eaa:0x3ffbf870 0x40087ca5:0x3ffbf8a0 0x400819d5:0x3ffcbfc0 0x400819b1:0x3ffcbff0 0x400ec770:0x3ffcc010 0x400ec96a:0x3ffcc030 0x4011aaf1:0x3ffcc060 0x4011ad7a:0x3ffcc080 0x40136bc1:0x3ffcc0a0        
=> 0x40082eaa: i2s_ll_get_intr_status at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/hal/esp32/include/hal/i2s_ll.h:398
      (inlined by) i2s_intr_handler_default at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/driver/i2s.c:434
=> 0x40087ca5: _xt_medint2 at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/freertos/port/xtensa/xtensa_vectors.S:1203
=> 0x400819d5: BusDigital::setPixelColor(unsigned int, unsigned int) at wled00/bus_manager.cpp:265
      (inlined by) BusDigital::setPixelColor(unsigned int, unsigned int) at wled00/bus_manager.cpp:263
=> 0x400819b1: BusManager::setPixelColor(unsigned int, unsigned int) at wled00/bus_manager.cpp:964
=> 0x400ec770: WS2812FX::show() at wled00/FX_fcn.cpp:1595
      (inlined by) WS2812FX::show() at wled00/FX_fcn.cpp:1554
=> 0x400ec96a: WS2812FX::service() at wled00/FX_fcn.cpp:1284
=> 0x4011aaf1: WLED::loop() at wled00/wled.cpp:130 (discriminator 5)
=> 0x4011ad7a: loop() at wled00/wled_main.cpp:23
=> 0x40136bc1: loopTask(void*) at C:/Users/dedehai/.platformio/packages/framework-arduinoespressif32/cores/esp32/main.cpp:50




ELF file SHA256: 0000000000000000

Rebooting...
ets Jul 29 2019 12:21:46

rst:0xc (SW_CPU_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
configsip: 0, SPIWP:0xee
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
mode:DIO, clock div:1
load:0x3fff0030,len:344
load:0x40078000,len:13412
=> 0x40078000: ?? ??:0
load:0x40080400,len:3480
=...

</details>
Fixes wled/WLED#4911

<!-- START COPILOT CODING AGENT TIPS -->
---

✨ Let Copilot coding agent [set things up for you](https://github.com/wled/WLED/issues/new?title=✨+Set+up+Copilot+instructions&body=Configure%20instructions%20for%20this%20repository%20as%20documented%20in%20%5BBest%20practices%20for%20Copilot%20coding%20agent%20in%20your%20repository%5D%28https://gh.io/copilot-coding-agent-tips%29%2E%0A%0A%3COnboard%20this%20repo%3E&assignees=copilot) — coding agent works faster and does higher quality work when set up for your repo.

Copy link
Contributor

coderabbitai bot commented Oct 2, 2025

Important

Review skipped

Bot user detected.

To trigger a single review, invoke the @coderabbitai review command.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.


Comment @coderabbitai help to get the list of available commands and usage tips.

@Copilot Copilot AI changed the title [WIP] Saving 2D config with higher LED count than configured leads to crash Fix crash when saving 2D config with panel size larger than configured LED count Oct 2, 2025
@Copilot Copilot AI requested a review from DedeHai October 2, 2025 17:48
Copilot finished work on behalf of DedeHai October 2, 2025 17:48
@blazoncek
Copy link
Collaborator

FYI There is no need to call suspend() or resume() from loop() context.

A much better solution is to remove suspend/resume logic from ledmap creation entirely and handle suspend/resume in set.cpp only.

@DedeHai
Copy link
Collaborator

DedeHai commented Oct 2, 2025

welcome back :) can you instruct copilot to do that?

@blazoncek
Copy link
Collaborator

can you instruct copilot to do that?

No, but it will be in my fork shortly. Once I fly back home.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants