Skip to content

Commit 019cafc

Browse files
committed
report out-of-memory situations to the user
1 parent b27686b commit 019cafc

File tree

6 files changed

+42
-11
lines changed

6 files changed

+42
-11
lines changed

wled00/FX_2Dfcn.cpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,10 @@ void WS2812FX::setUpMatrix() {
8080
if ((size > 0) && (customMappingTable == nullptr)) { // second try
8181
DEBUG_PRINTLN("setUpMatrix: trying to get fresh memory block.");
8282
customMappingTable = (uint16_t*) calloc(size, sizeof(uint16_t));
83-
if (customMappingTable == nullptr) USER_PRINTLN("setUpMatrix: alloc failed");
83+
if (customMappingTable == nullptr) {
84+
USER_PRINTLN("setUpMatrix: alloc failed");
85+
errorFlag = ERR_LOW_MEM; // WLEDMM raise errorflag
86+
}
8487
}
8588
if (customMappingTable != nullptr) customMappingTableSize = size;
8689
}
@@ -159,6 +162,7 @@ void WS2812FX::setUpMatrix() {
159162
} else { // memory allocation error
160163
customMappingTableSize = 0;
161164
USER_PRINTLN(F("Ledmap alloc error."));
165+
errorFlag = ERR_LOW_MEM; // WLEDMM raise errorflag
162166
isMatrix = false; //WLEDMM does not like this done in teh background while end users are confused whats happened...
163167
panels = 0;
164168
panel.clear();

wled00/FX_fcn.cpp

Lines changed: 24 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -128,10 +128,13 @@ void Segment::allocLeds() {
128128
if (ledsrgb) free(ledsrgb); // we need a bigger buffer, so free the old one first
129129
ledsrgb = (CRGB*)calloc(size, 1);
130130
ledsrgbSize = ledsrgb?size:0;
131-
if (ledsrgb == nullptr) USER_PRINTLN("allocLeds failed!!");
131+
if (ledsrgb == nullptr) {
132+
USER_PRINTLN("allocLeds failed!!");
133+
errorFlag = ERR_LOW_MEM; // WLEDMM raise errorflag
134+
}
132135
}
133136
else {
134-
USER_PRINTF("reuse Leds %u from %u\n", size, ledsrgb?ledsrgbSize:0);
137+
//USER_PRINTF("reuse Leds %u from %u\n", size, ledsrgb?ledsrgbSize:0);
135138
}
136139
}
137140

@@ -212,26 +215,37 @@ bool Segment::allocateData(size_t len) {
212215
//DEBUG_PRINTF("allocateData(%u) start %d, stop %d, vlen %d\n", len, start, stop, virtualLength());
213216
deallocateData();
214217
if (len == 0) return false; // nothing to do
215-
if (Segment::getUsedSegmentData() + len > MAX_SEGMENT_DATA) return false; //not enough memory
218+
if (Segment::getUsedSegmentData() + len > MAX_SEGMENT_DATA) {
219+
//USER_PRINTF("Segment::allocateData: Segment data quota exceeded! used:%u request:%u max:%d\n", Segment::getUsedSegmentData(), len, MAX_SEGMENT_DATA);
220+
if (len > 0) errorFlag = ERR_LOW_SEG_MEM; // WLEDMM raise errorflag
221+
return false; //not enough memory
222+
}
216223
// do not use SPI RAM on ESP32 since it is slow
217224
//#if defined(ARDUINO_ARCH_ESP32) && defined(BOARD_HAS_PSRAM) && defined(WLED_USE_PSRAM)
218225
//if (psramFound())
219226
// data = (byte*) ps_malloc(len);
220227
//else
221228
//#endif
222229
data = (byte*) malloc(len);
223-
if (!data) { _dataLen = 0; return false;} //allocation failed // WLEDMM reset dataLen
230+
if (!data) {
231+
_dataLen = 0; // WLEDMM reset dataLen
232+
errorFlag = ERR_LOW_MEM; // WLEDMM raise errorflag
233+
USER_PRINT(F("Segment::allocateData: FAILED to allocate "));
234+
USER_PRINT(len); USER_PRINTLN(F(" bytes."));
235+
return false;
236+
} //allocation failed
224237
Segment::addUsedSegmentData(len);
225238
_dataLen = len;
226239
memset(data, 0, len);
240+
if (errorFlag == ERR_LOW_SEG_MEM) errorFlag = ERR_NONE; // WLEDMM reset errorflag on success
227241
return true;
228242
}
229243

230244
void Segment::deallocateData() {
231245
if (!data) {_dataLen = 0; return;} // WLEDMM reset dataLen
232246
free(data);
233247
data = nullptr;
234-
//DEBUG_PRINTLN("deallocateData() called free().");
248+
//USER_PRINTF("Segment::deallocateData: free'd %d bytes.\n", _dataLen);
235249
Segment::addUsedSegmentData(-_dataLen);
236250
_dataLen = 0;
237251
}
@@ -1656,6 +1670,7 @@ void WS2812FX::finalizeInit(void)
16561670
//#endif
16571671
if (arrSize > 0) Segment::_globalLeds = (CRGB*) malloc(arrSize); // WLEDMM avoid malloc(0)
16581672
if ((Segment::_globalLeds != nullptr) && (arrSize > 0)) memset(Segment::_globalLeds, 0, arrSize); // WLEDMM avoid dereferencing nullptr
1673+
if ((Segment::_globalLeds == nullptr) && (arrSize > 0)) errorFlag = ERR_LOW_MEM; // WLEDMM raise errorflag
16591674
}
16601675

16611676
//segments are created in makeAutoSegments();
@@ -2403,7 +2418,10 @@ bool WS2812FX::deserializeMap(uint8_t n) {
24032418
if ((size > 0) && (customMappingTable == nullptr)) { // second try
24042419
DEBUG_PRINTLN("deserializeMap: trying to get fresh memory block.");
24052420
customMappingTable = (uint16_t*) calloc(size, sizeof(uint16_t));
2406-
if (customMappingTable == nullptr) DEBUG_PRINTLN("deserializeMap: alloc failed!");
2421+
if (customMappingTable == nullptr) {
2422+
DEBUG_PRINTLN("deserializeMap: alloc failed!");
2423+
errorFlag = ERR_LOW_MEM; // WLEDMM raise errorflag
2424+
}
24072425
}
24082426
if (customMappingTable != nullptr) customMappingTableSize = size;
24092427
}

wled00/const.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -347,7 +347,9 @@
347347
#define ERR_OVERTEMP 30 // An attached temperature sensor has measured above threshold temperature (not implemented)
348348
#define ERR_OVERCURRENT 31 // An attached current sensor has measured a current above the threshold (not implemented)
349349
#define ERR_UNDERVOLT 32 // An attached voltmeter has measured a voltage below the threshold (not implemented)
350-
#define ERR_LOW_MEM 33 // low memory (RAM)
350+
#define ERR_LOW_MEM 33 // WLEDMM: low memory (RAM)
351+
#define ERR_LOW_SEG_MEM 34 // WLEDMM: low memory (segment data RAM)
352+
#define ERR_LOW_WS_MEM 35 // WLEDMM: low memory (ws)
351353

352354
// Timer mode types
353355
#define NL_MODE_SET 0 //After nightlight time elapsed, set to target brightness

wled00/data/index.js

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1968,8 +1968,14 @@ function readState(s,command=false)
19681968
errstr = "A filesystem error has occured.";
19691969
break;
19701970
case 33:
1971-
errstr = "Warning: Low Memory (RAM).";
1972-
break;
1971+
errstr = "Low Memory (generic RAM).";
1972+
break;
1973+
case 34:
1974+
errstr = "Low Memory (effect data).";
1975+
break;
1976+
case 35:
1977+
errstr = "Low Memory (WS data).";
1978+
break;
19731979
}
19741980
showToast('Error ' + s.error + ": " + errstr, true);
19751981
}

wled00/wled.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*/
99

1010
// version code in format yymmddb (b = daily build)
11-
#define VERSION 2404091
11+
#define VERSION 2404161
1212

1313
// WLEDMM - you can check for this define in usermods, to only enabled WLEDMM specific code in the "right" fork. Its not defined in AC WLED.
1414
#define _MoonModules_WLED_

wled00/ws.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,7 @@ void sendDataWs(AsyncWebSocketClient * client)
162162
ws.closeAll(1013); //code 1013 = temporary overload, try again later
163163
ws.cleanupClients(0); //disconnect all clients to release memory
164164
ws._cleanBuffers();
165+
errorFlag = ERR_LOW_WS_MEM;
165166
return; //out of memory
166167
}
167168

0 commit comments

Comments
 (0)