fixing some memory leaks

* audio_reactive.h: catch memory errors from WiFiUDP
* udp: explicitly flush unused receive buffers.
* wled.cpp: additional debug info about "largest available block"
* FX_fcn.cpp: free _globalLeds before running purgeSegments().
This commit is contained in:
Frank
2023-06-07 17:10:32 +02:00
parent 309e66bf8a
commit af6091b493
4 changed files with 30 additions and 13 deletions

View File

@@ -1378,9 +1378,10 @@ class AudioReactive : public Usermod {
transmitData.FFT_Magnitude = my_magnitude;
transmitData.FFT_MajorPeak = FFT_MajorPeak;
fftUdp.beginMulticastPacket();
fftUdp.write(reinterpret_cast<uint8_t *>(&transmitData), sizeof(transmitData));
fftUdp.endPacket();
if (fftUdp.beginMulticastPacket() != 0) { // beginMulticastPacket returns 0 in case of error
fftUdp.write(reinterpret_cast<uint8_t *>(&transmitData), sizeof(transmitData));
fftUdp.endPacket();
}
return;
} // transmitAudioData()
@@ -1448,7 +1449,21 @@ class AudioReactive : public Usermod {
if (!udpSyncConnected) return false;
bool haveFreshData = false;
size_t packetSize = fftUdp.parsePacket();
size_t packetSize = 0;
// WLEDMM use exception handler to catch out-of-memory errors
#if __cpp_exceptions
try{
packetSize = fftUdp.parsePacket();
} catch(...) {
packetSize = 0; // low heap memory -> discard packet.
fftUdp.flush();
DEBUG_PRINTLN(F("receiveAudioData: parsePacket out of memory exception caught!"));
USER_FLUSH();
}
#else
packetSize = fftUdp.parsePacket();
#endif
if ((packetSize > 0) && ((packetSize < 5) || (packetSize > UDPSOUND_MAX_PACKET))) fftUdp.flush(); // discard invalid packets (too small or too big)
if ((packetSize > 5) && (packetSize <= UDPSOUND_MAX_PACKET)) {
static uint8_t fftUdpBuffer[UDPSOUND_MAX_PACKET+1] = { 0 }; // static buffer for receiving, to reuse the same memory and avoid heap fragmentation

View File

@@ -1494,9 +1494,9 @@ void WS2812FX::finalizeInit(void)
//initialize leds array. TBD: realloc if nr of leds change
if (Segment::_globalLeds) {
purgeSegments(true);
free(Segment::_globalLeds);
Segment::_globalLeds = nullptr;
purgeSegments(true); // WLEDMM moved here, because it seems to improve stability.
}
if (useLedsArray && getLengthTotal()>0) { // WLEDMM avoid malloc(0)
size_t arrSize = sizeof(CRGB) * getLengthTotal();

View File

@@ -243,14 +243,14 @@ void handleNotifications()
if (!packetSize && udpRgbConnected) {
packetSize = rgbUdp.parsePacket();
if (packetSize) {
if (!receiveDirect) return;
if (packetSize > UDP_IN_MAXSIZE || packetSize < 3) return;
if (!receiveDirect) {rgbUdp.flush(); notifierUdp.flush(); notifier2Udp.flush(); return;}
if (packetSize > UDP_IN_MAXSIZE || packetSize < 3) {rgbUdp.flush(); notifierUdp.flush(); notifier2Udp.flush(); return;}
realtimeIP = rgbUdp.remoteIP();
DEBUG_PRINTLN(rgbUdp.remoteIP());
uint8_t lbuf[packetSize];
rgbUdp.read(lbuf, packetSize);
realtimeLock(realtimeTimeoutMs, REALTIME_MODE_HYPERION);
if (realtimeOverride && !(realtimeMode && useMainSegmentOnly)) return;
if (realtimeOverride && !(realtimeMode && useMainSegmentOnly)) {notifierUdp.flush(); notifier2Udp.flush(); return;}
uint16_t id = 0;
uint16_t totalLen = strip.getLengthTotal();
for (size_t i = 0; i < packetSize -2; i += 3)
@@ -263,12 +263,12 @@ void handleNotifications()
}
}
if (!(receiveNotifications || receiveDirect)) return;
if (!(receiveNotifications || receiveDirect)) {notifierUdp.flush(); notifier2Udp.flush(); return;}
localIP = Network.localIP();
//notifier and UDP realtime
if (!packetSize || packetSize > UDP_IN_MAXSIZE) return;
if (!isSupp && notifierUdp.remoteIP() == localIP) return; //don't process broadcasts we send ourselves
if (!packetSize || packetSize > UDP_IN_MAXSIZE) {notifierUdp.flush(); notifier2Udp.flush(); return;}
if (!isSupp && notifierUdp.remoteIP() == localIP) {notifierUdp.flush(); notifier2Udp.flush(); return;}; //don't process broadcasts we send ourselves
uint8_t udpIn[packetSize +1];
uint16_t len;

View File

@@ -278,14 +278,16 @@ void WLED::loop()
DEBUG_PRINT(F("Name: ")); DEBUG_PRINTLN(serverDescription);
DEBUG_PRINT(F("Runtime: ")); DEBUG_PRINTLN(millis());
DEBUG_PRINT(F("Unix time: ")); toki.printTime(toki.getTime());
DEBUG_PRINT(F("Free heap: ")); DEBUG_PRINTLN(ESP.getFreeHeap());
DEBUG_PRINT(F("Free heap : ")); DEBUG_PRINTLN(ESP.getFreeHeap());
#ifdef ARDUINO_ARCH_ESP32
DEBUG_PRINT(F("Avail heap: ")); DEBUG_PRINTLN(ESP.getMaxAllocHeap());
DEBUG_PRINTF("%s min free stack %d\n", pcTaskGetTaskName(NULL), uxTaskGetStackHighWaterMark(NULL)); //WLEDMM
#endif
#if defined(ARDUINO_ARCH_ESP32) && defined(BOARD_HAS_PSRAM)
if (psramFound()) {
//DEBUG_PRINT(F("Total PSRAM: ")); DEBUG_PRINT(ESP.getPsramSize()/1024); DEBUG_PRINTLN("kB");
DEBUG_PRINT(F("Free PSRAM: ")); DEBUG_PRINT(ESP.getFreePsram()/1024); DEBUG_PRINTLN("kB");
DEBUG_PRINT(F("Free PSRAM : ")); DEBUG_PRINT(ESP.getFreePsram()/1024); DEBUG_PRINTLN("kB");
DEBUG_PRINT(F("Avail PSRAM: ")); DEBUG_PRINT(ESP.:getMaxAllocPsram()/1024); DEBUG_PRINTLN("kB");
DEBUG_PRINT(F("PSRAM in use:")); DEBUG_PRINT(ESP.getPsramSize() - ESP.getFreePsram()); DEBUG_PRINTLN(F(" Bytes"));
} else {