report out-of-memory situations to the user

This commit is contained in:
Frank
2024-04-16 19:10:46 +02:00
parent b27686bd2b
commit 019cafc5e0
6 changed files with 42 additions and 11 deletions

View File

@@ -80,7 +80,10 @@ void WS2812FX::setUpMatrix() {
if ((size > 0) && (customMappingTable == nullptr)) { // second try
DEBUG_PRINTLN("setUpMatrix: trying to get fresh memory block.");
customMappingTable = (uint16_t*) calloc(size, sizeof(uint16_t));
if (customMappingTable == nullptr) USER_PRINTLN("setUpMatrix: alloc failed");
if (customMappingTable == nullptr) {
USER_PRINTLN("setUpMatrix: alloc failed");
errorFlag = ERR_LOW_MEM; // WLEDMM raise errorflag
}
}
if (customMappingTable != nullptr) customMappingTableSize = size;
}
@@ -159,6 +162,7 @@ void WS2812FX::setUpMatrix() {
} else { // memory allocation error
customMappingTableSize = 0;
USER_PRINTLN(F("Ledmap alloc error."));
errorFlag = ERR_LOW_MEM; // WLEDMM raise errorflag
isMatrix = false; //WLEDMM does not like this done in teh background while end users are confused whats happened...
panels = 0;
panel.clear();

View File

@@ -128,10 +128,13 @@ void Segment::allocLeds() {
if (ledsrgb) free(ledsrgb); // we need a bigger buffer, so free the old one first
ledsrgb = (CRGB*)calloc(size, 1);
ledsrgbSize = ledsrgb?size:0;
if (ledsrgb == nullptr) USER_PRINTLN("allocLeds failed!!");
if (ledsrgb == nullptr) {
USER_PRINTLN("allocLeds failed!!");
errorFlag = ERR_LOW_MEM; // WLEDMM raise errorflag
}
}
else {
USER_PRINTF("reuse Leds %u from %u\n", size, ledsrgb?ledsrgbSize:0);
//USER_PRINTF("reuse Leds %u from %u\n", size, ledsrgb?ledsrgbSize:0);
}
}
@@ -212,7 +215,11 @@ bool Segment::allocateData(size_t len) {
//DEBUG_PRINTF("allocateData(%u) start %d, stop %d, vlen %d\n", len, start, stop, virtualLength());
deallocateData();
if (len == 0) return false; // nothing to do
if (Segment::getUsedSegmentData() + len > MAX_SEGMENT_DATA) return false; //not enough memory
if (Segment::getUsedSegmentData() + len > MAX_SEGMENT_DATA) {
//USER_PRINTF("Segment::allocateData: Segment data quota exceeded! used:%u request:%u max:%d\n", Segment::getUsedSegmentData(), len, MAX_SEGMENT_DATA);
if (len > 0) errorFlag = ERR_LOW_SEG_MEM; // WLEDMM raise errorflag
return false; //not enough memory
}
// do not use SPI RAM on ESP32 since it is slow
//#if defined(ARDUINO_ARCH_ESP32) && defined(BOARD_HAS_PSRAM) && defined(WLED_USE_PSRAM)
//if (psramFound())
@@ -220,10 +227,17 @@ bool Segment::allocateData(size_t len) {
//else
//#endif
data = (byte*) malloc(len);
if (!data) { _dataLen = 0; return false;} //allocation failed // WLEDMM reset dataLen
if (!data) {
_dataLen = 0; // WLEDMM reset dataLen
errorFlag = ERR_LOW_MEM; // WLEDMM raise errorflag
USER_PRINT(F("Segment::allocateData: FAILED to allocate "));
USER_PRINT(len); USER_PRINTLN(F(" bytes."));
return false;
} //allocation failed
Segment::addUsedSegmentData(len);
_dataLen = len;
memset(data, 0, len);
if (errorFlag == ERR_LOW_SEG_MEM) errorFlag = ERR_NONE; // WLEDMM reset errorflag on success
return true;
}
@@ -231,7 +245,7 @@ void Segment::deallocateData() {
if (!data) {_dataLen = 0; return;} // WLEDMM reset dataLen
free(data);
data = nullptr;
//DEBUG_PRINTLN("deallocateData() called free().");
//USER_PRINTF("Segment::deallocateData: free'd %d bytes.\n", _dataLen);
Segment::addUsedSegmentData(-_dataLen);
_dataLen = 0;
}
@@ -1656,6 +1670,7 @@ void WS2812FX::finalizeInit(void)
//#endif
if (arrSize > 0) Segment::_globalLeds = (CRGB*) malloc(arrSize); // WLEDMM avoid malloc(0)
if ((Segment::_globalLeds != nullptr) && (arrSize > 0)) memset(Segment::_globalLeds, 0, arrSize); // WLEDMM avoid dereferencing nullptr
if ((Segment::_globalLeds == nullptr) && (arrSize > 0)) errorFlag = ERR_LOW_MEM; // WLEDMM raise errorflag
}
//segments are created in makeAutoSegments();
@@ -2403,7 +2418,10 @@ bool WS2812FX::deserializeMap(uint8_t n) {
if ((size > 0) && (customMappingTable == nullptr)) { // second try
DEBUG_PRINTLN("deserializeMap: trying to get fresh memory block.");
customMappingTable = (uint16_t*) calloc(size, sizeof(uint16_t));
if (customMappingTable == nullptr) DEBUG_PRINTLN("deserializeMap: alloc failed!");
if (customMappingTable == nullptr) {
DEBUG_PRINTLN("deserializeMap: alloc failed!");
errorFlag = ERR_LOW_MEM; // WLEDMM raise errorflag
}
}
if (customMappingTable != nullptr) customMappingTableSize = size;
}

View File

@@ -347,7 +347,9 @@
#define ERR_OVERTEMP 30 // An attached temperature sensor has measured above threshold temperature (not implemented)
#define ERR_OVERCURRENT 31 // An attached current sensor has measured a current above the threshold (not implemented)
#define ERR_UNDERVOLT 32 // An attached voltmeter has measured a voltage below the threshold (not implemented)
#define ERR_LOW_MEM 33 // low memory (RAM)
#define ERR_LOW_MEM 33 // WLEDMM: low memory (RAM)
#define ERR_LOW_SEG_MEM 34 // WLEDMM: low memory (segment data RAM)
#define ERR_LOW_WS_MEM 35 // WLEDMM: low memory (ws)
// Timer mode types
#define NL_MODE_SET 0 //After nightlight time elapsed, set to target brightness

View File

@@ -1968,8 +1968,14 @@ function readState(s,command=false)
errstr = "A filesystem error has occured.";
break;
case 33:
errstr = "Warning: Low Memory (RAM).";
break;
errstr = "Low Memory (generic RAM).";
break;
case 34:
errstr = "Low Memory (effect data).";
break;
case 35:
errstr = "Low Memory (WS data).";
break;
}
showToast('Error ' + s.error + ": " + errstr, true);
}

View File

@@ -8,7 +8,7 @@
*/
// version code in format yymmddb (b = daily build)
#define VERSION 2404091
#define VERSION 2404161
// 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.
#define _MoonModules_WLED_

View File

@@ -162,6 +162,7 @@ void sendDataWs(AsyncWebSocketClient * client)
ws.closeAll(1013); //code 1013 = temporary overload, try again later
ws.cleanupClients(0); //disconnect all clients to release memory
ws._cleanBuffers();
errorFlag = ERR_LOW_WS_MEM;
return; //out of memory
}