improve robustness when heap is low
* customMappingTable: allocate using calloc instead of new (new will throw exception if nor enough heap) * fixing a few minor memory leaks * ws.cpp: catch out-of-memory in sendLiveLedsWs * ws.cpp: change interval to 80ms (120 ws very slow...)
This commit is contained in:
@@ -941,8 +941,8 @@ class WS2812FX { // 96 bytes
|
||||
|
||||
show_callback _callback;
|
||||
|
||||
uint16_t* customMappingTable;
|
||||
uint16_t customMappingSize;
|
||||
uint16_t* customMappingTable = nullptr;
|
||||
uint16_t customMappingSize = 0;
|
||||
|
||||
/*uint32_t*/ unsigned long _lastShow; // WLEDMM avoid losing precision
|
||||
|
||||
|
||||
@@ -37,7 +37,8 @@
|
||||
void WS2812FX::setUpMatrix() {
|
||||
#ifndef WLED_DISABLE_2D
|
||||
// erase old ledmap, just in case.
|
||||
if (customMappingTable != nullptr) delete[] customMappingTable;
|
||||
//if (customMappingTable != nullptr) delete[] customMappingTable;
|
||||
if (customMappingTable != nullptr) free(customMappingTable);
|
||||
customMappingTable = nullptr;
|
||||
customMappingSize = 0;
|
||||
|
||||
@@ -68,7 +69,9 @@ void WS2812FX::setUpMatrix() {
|
||||
return;
|
||||
}
|
||||
|
||||
customMappingTable = new uint16_t[Segment::maxWidth * Segment::maxHeight];
|
||||
//customMappingTable = new uint16_t[Segment::maxWidth * Segment::maxHeight];
|
||||
if (nullptr != customMappingTable) free(customMappingTable);
|
||||
customMappingTable = (uint16_t *) calloc(Segment::maxWidth * Segment::maxHeight, sizeof(uint16_t));
|
||||
|
||||
if (customMappingTable != nullptr) {
|
||||
customMappingSize = Segment::maxWidth * Segment::maxHeight;
|
||||
|
||||
@@ -591,7 +591,8 @@ class JMapC {
|
||||
if (jVectorMap.size() > 0) {
|
||||
USER_PRINTLN("delete jVectorMap");
|
||||
for (size_t i=0; i<jVectorMap.size(); i++)
|
||||
delete jVectorMap[i].array;
|
||||
// delete jVectorMap[i].array; // original code
|
||||
if (jVectorMap[i].array) { delete[] jVectorMap[i].array; jVectorMap[i].array = nullptr; } // softhack007 quickfix for memory leak
|
||||
jVectorMap.clear();
|
||||
}
|
||||
}
|
||||
@@ -653,7 +654,7 @@ class JMapC {
|
||||
if (err)
|
||||
{
|
||||
USER_PRINTF("deserializeJson() of parseTree failed with code %s\n", err.c_str());
|
||||
delete[] SEGMENT.name; SEGMENT.name = nullptr; //need to clear the name as otherwise continuously loaded
|
||||
if (SEGMENT.name) delete[] SEGMENT.name; SEGMENT.name = nullptr; //need to clear the name as otherwise continuously loaded // softhack007 avoid deleting nullptr
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -2092,7 +2093,8 @@ bool WS2812FX::deserializeMap(uint8_t n) {
|
||||
//WLEDM: doubt this is necessary as return false causes setupMatrix to deal with this
|
||||
if (!isMatrix && !n && customMappingTable != nullptr) {
|
||||
customMappingSize = 0;
|
||||
delete[] customMappingTable;
|
||||
//delete[] customMappingTable;
|
||||
free(customMappingTable);
|
||||
customMappingTable = nullptr;
|
||||
loadedLedmap = 0; //WLEDMM
|
||||
}
|
||||
@@ -2112,7 +2114,8 @@ bool WS2812FX::deserializeMap(uint8_t n) {
|
||||
// erase old custom ledmap
|
||||
if (customMappingTable != nullptr) {
|
||||
customMappingSize = 0;
|
||||
delete[] customMappingTable;
|
||||
//delete[] customMappingTable;
|
||||
free(customMappingTable); // softhack007 use calloc / free, as they behave better when heap is low
|
||||
customMappingTable = nullptr;
|
||||
loadedLedmap = 0;
|
||||
}
|
||||
@@ -2122,13 +2125,22 @@ bool WS2812FX::deserializeMap(uint8_t n) {
|
||||
|
||||
//WLEDMM: support ledmap file properties width and height
|
||||
if (doc[F("width")]>0 && doc[F("height")]>0) {
|
||||
Segment::maxWidth = doc[F("width")];;
|
||||
Segment::maxHeight = doc[F("height")];;
|
||||
Segment::maxWidth = doc[F("width")];
|
||||
Segment::maxHeight = doc[F("height")];
|
||||
resetSegments(true); //WLEDMM not makeAutoSegments() as we only want to change bounds
|
||||
}
|
||||
|
||||
customMappingSize = map.size();
|
||||
customMappingTable = new uint16_t[customMappingSize];
|
||||
if (nullptr != customMappingTable) free(customMappingTable);
|
||||
//customMappingTable = new uint16_t[customMappingSize];
|
||||
customMappingTable = (uint16_t *) calloc(customMappingSize+1, sizeof(uint16_t)); // softhack007 use calloc / free, as they behave better when heap is low
|
||||
if (nullptr == customMappingTable) { // WLEDMM handle out-of-memory
|
||||
USER_PRINTF("deserializeMap(): cannot alloate %d bytes for customMappingTable[]\n", sizeof(uint16_t) * (customMappingSize+1));
|
||||
customMappingSize = 0;
|
||||
loadedLedmap = 0;
|
||||
releaseJSONBufferLock();
|
||||
return false; //if not enough memory - just exit
|
||||
}
|
||||
|
||||
for (uint16_t i=0; i<customMappingSize; i++)
|
||||
customMappingTable[i] = (uint16_t) (map[i]<0 ? 0xFFFFU : map[i]);
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
//#define WLED_DEBUG_NTP
|
||||
#define NTP_SYNC_INTERVAL 42000UL //Get fresh NTP time about twice per day
|
||||
|
||||
Timezone* tz;
|
||||
Timezone* tz = nullptr;
|
||||
|
||||
#define TZ_UTC 0
|
||||
#define TZ_UK 1
|
||||
@@ -38,7 +38,7 @@ Timezone* tz;
|
||||
byte tzCurrent = TZ_INIT; //uninitialized
|
||||
|
||||
void updateTimezone() {
|
||||
delete tz;
|
||||
if (tz) {delete tz; tz = nullptr;}
|
||||
TimeChangeRule tcrDaylight = {Last, Sun, Mar, 1, 0}; //UTC
|
||||
TimeChangeRule tcrStandard = tcrDaylight; //UTC
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
*/
|
||||
|
||||
// version code in format yymmddb (b = daily build)
|
||||
#define VERSION 2305080
|
||||
#define VERSION 2305150
|
||||
|
||||
//uncomment this if you have a "my_config.h" file you'd like to use
|
||||
//#define WLED_USE_MY_CONFIG
|
||||
|
||||
@@ -10,7 +10,7 @@ static volatile unsigned long wsLastLiveTime = 0; // WLEDMM
|
||||
//uint8_t* wsFrameBuffer = nullptr;
|
||||
|
||||
#ifdef WLEDMM_FASTPATH
|
||||
#define WS_LIVE_INTERVAL 120 // WLEDMM reduced update interval, to have more time for LEDs
|
||||
#define WS_LIVE_INTERVAL 80 // WLEDMM reduced update interval, to have more time for LEDs
|
||||
#else
|
||||
#define WS_LIVE_INTERVAL 40
|
||||
#endif
|
||||
@@ -177,9 +177,25 @@ static bool sendLiveLedsWs(uint32_t wsClient) // WLEDMM added "static"
|
||||
size_t bufSize = pos + (used/n)*3;
|
||||
//WLEDMM: no skipLines
|
||||
|
||||
AsyncWebSocketMessageBuffer * wsBuf = ws.makeBuffer(bufSize);
|
||||
if (bufSize < 1) return(false); // WLEDMM should not happen
|
||||
//AsyncWebSocketMessageBuffer * wsBuf = ws.makeBuffer(bufSize);
|
||||
// WLEDMM protect against exceptions due to low memory
|
||||
AsyncWebSocketMessageBuffer * wsBuf = nullptr;
|
||||
try{
|
||||
wsBuf = ws.makeBuffer(bufSize);
|
||||
} catch(...) {
|
||||
wsBuf = nullptr;
|
||||
DEBUG_PRINTLN(F("WS buffer allocation failed, dropping connections."));
|
||||
ws.closeAll(1013); //code 1013 = temporary overload, try again later
|
||||
ws.cleanupClients(0); //disconnect all clients to release memory
|
||||
ws._cleanBuffers();
|
||||
}
|
||||
|
||||
if (!wsBuf) return false; //out of memory
|
||||
uint8_t* buffer = wsBuf->get();
|
||||
if (!buffer) return false; //out of memory
|
||||
|
||||
wsBuf->lock(); // protect buffer from being cleaned by another WS instance
|
||||
buffer[0] = 'L';
|
||||
buffer[1] = 1; //version
|
||||
#ifndef WLED_DISABLE_2D
|
||||
@@ -201,6 +217,8 @@ static bool sendLiveLedsWs(uint32_t wsClient) // WLEDMM added "static"
|
||||
}
|
||||
|
||||
wsc->binary(wsBuf);
|
||||
wsBuf->unlock(); // un-protect buffer
|
||||
ws._cleanBuffers(); // cleans up if the message is not added to any clients.
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user