arduinoWebSockets
arduinoWebSockets copied to clipboard
Multi heap poisioning. ( ESP 32 )
- Esp32 ( wrover with psram )
- Platformio
CORRUPT HEAP on async web page refresh
CORRUPT HEAP: Bad head at 0x3ffb3f54. Expected 0xabba1234 got 0x3ffb0014
assert failed: multi_heap_free multi_heap_poisoning.c:253 (head != NULL)
Backtrace:0x40083ded:0x3ffe6ab00x4008e605:0x3ffe6ad0 0x40093bcd:0x3ffe6af0 0x40093813:0x3ffe6c20 0x400842d1:0x3ffe6c40 0x40093bfd:0x3ffe6c60 0x4018db0d:0x3ffe6c80 0x40190a50:0x3ffe6ca0 0x400f1cf9:0x3ffe6cc0 0x401a8ca3:0x3ffe6ce0 0x400f0f73:0x3ffe6d00 0x400f100d:0x3ffe6d40 0x400f1023:0x3ffe6d60 0x400d3bb9:0x3ffe6d80 0x400ea52a:0x3ffe6df0 0x400dbc72:0x3ffe6e10 0x400dca77:0x3ffe6e70 0x400ee1a1:0x3ffe6e90 0x400ee230:0x3ffe6eb0 0x400ef315:0x3ffe6ed0
#0 0x40083ded:0x3ffe6ab00 in panic_abort at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/esp_system/panic.c:402
DECODED:
0x40083ded: panic_abort at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/esp_system/panic.c line 402
0x4008e605: esp_system_abort at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/esp_system/esp_system.c line 121
0x40093bcd: __assert_func at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/newlib/assert.c line 85
0x40093813: multi_heap_free at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/heap/multi_heap_poisoning.c line 245
0x400842d1: heap_caps_free at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/heap/heap_caps.c line 305
0x40093bfd: free at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/newlib/heap.c line 46
0x4018db0d: operator delete(void*) at /builds/idf/crosstool-NG/.build/HOST-x86_64-w64-mingw32/xtensa-esp32-elf/src/gcc/libstdc++-v3/libsupc++/del_op.cc line 49
0x40190a50: WiFiClient::~WiFiClient() at C:/Users/Pc/.platformio/packages/framework-arduinoespressif32/libraries/WiFi/src/WiFiClient.cpp line 188
0x400f1cf9: WebSocketsClient::clientDisconnect(WSclient_t*) at lib/arduinoWebSockets/src/WebSocketsClient.cpp line 500
0x401a8ca3: WebSocketsClient::clientIsConnected(WSclient_t*) at lib/arduinoWebSockets/src/WebSocketsClient.cpp line 541
0x400f0f73: SocketIOclient::send(socketIOmessageType_t, unsigned char*, unsigned int, bool) at lib/arduinoWebSockets/src/SocketIOclient.cpp line 110
0x400f100d: SocketIOclient::sendEVENT(unsigned char*, unsigned int, bool) at lib/arduinoWebSockets/src/SocketIOclient.cpp line 155
0x400f1023: SocketIOclient::sendEVENT(char*, unsigned int, bool) at lib/arduinoWebSockets/src/SocketIOclient.cpp line 163
0x400d3bb9: serverCommSys::redirect(char const*) at src/utilities/HsHServerComm.cpp line 38
0x400ea52a: sSystem::socketSendString(char const*, int, int, bool) at src/utilities/serverSystem.cpp line 707
0x400dbc72: thermSystem::sendPeriodicMessage() at src/utilities/components/therms.cpp line 400
0x400dca77: thermSystem::loop() at src/utilities/components/therms.cpp line 824
0x400ee1a1: zSystem::runTherms() at src/utilities/zones.cpp line 535
0x400ee230: zSystem::runComponents() at src/utilities/zones.cpp line 626
0x400ef315: zonesTask(void*) at src/utilities/zones.cpp line 637
My application is using the async websockets for local client communication. But i needed this library to do a server communication trought socket io. The application is wrapping every async socket message to send it to a socket io server.
Here is the wrapper function which wraps all the packets to another packet to be compatible with socket io
boolean serverCommSys::redirect(const char* message){
if( connected ){
//Serial.printf("Wrapping socket message for HsH server\n");
char * messageString = (char *) ps_malloc (REDIRECT_MESSAGE_SIZE * sizeof (char));
SpiRamJsonDocument wrapperDoc(REDIRECT_MESSAGE_SIZE);
JsonArray wrapperArray = wrapperDoc.to<JsonArray>();
if (messageString != NULL){
wrapperArray.add("espMessage");
JsonObject wrapperObj = wrapperArray.createNestedObject();
wrapperObj["message"] = message;
wrapperObj["moduleKey"] = ESP.getEfuseMac();
if( serializeJson(wrapperArray,messageString,REDIRECT_MESSAGE_SIZE) > 0 ){
socketIO.sendEVENT(messageString);
free(messageString);
return true;
}
free(messageString);
}
return false;
}
return false;
}
This decode shows that the crash was in fact at WebSocketsClient::clientDisconnect(WSclient_t*)
and not on my redirect function.
The socket handler event is in the main loop alone, and my event callback looks like this:
void serverCommSys::socketIOEvent(socketIOmessageType_t type, uint8_t * payload, size_t length) {
switch(type) {
case sIOtype_DISCONNECT:
Serial.printf("IO - Disconnected!\n");
hsh_ServerComSys.setConnected(false);
break;
case sIOtype_CONNECT:
Serial.printf("IO - Connected to url: %s\n", payload);
socketIO.send(sIOtype_CONNECT, "/");
hsh_ServerComSys.setConnected(true);
hsh_ServerComSys.joinToRoom();
break;
case sIOtype_EVENT:
//hsh_Performance.timeMeasStart();
SpiRamJsonDocument socketJsonBuffer(MAIN_SOCKET_BUFFER_SIZE);
DeserializationError error = deserializeJson(socketJsonBuffer, payload, MAIN_SOCKET_BUFFER_SIZE);
if ( !error ) {
JsonArray socketArray = socketJsonBuffer.as<JsonArray>();
JsonObject payloadObj = socketArray[1].as<JsonObject>();
if( serializeJson(payloadObj, hsh_Server.mainSocketBuffer, length) ){
hsh_Server.handleSocketMessages();
//hsh_Performance.timeMeasEnd();
}
}else{
Serial.printf("IO - Deserialization Error: %s\n", error.c_str());
}
break;
}
}
EDIT:
I have three functions for sending on local websocket connection. In every case, the pointer to the messsage is properly freed.
void sSystem::socketSendStringExcept(const char *message, int socket, int clientIDToExclude, boolean shouldRedirect) {
socketLock();
if (socket == MAIN_SOCKET && hsh_Socket.count() > 0) {
if( shouldRedirect ){
hsh_ServerComSys.redirect(message);
}
hsh_Socket.textAllExcept(message, clientIDToExclude);
} else if (socket == ADMIN_SOCKET && hsh_adminSocket.count() > 0) {
hsh_adminSocket.textAllExcept(message, clientIDToExclude);
}
socketUnlock();
}
void sSystem::socketSendString(const char *message, int socket, int clientID, boolean shouldRedirect) {
socketLock();
if (socket == MAIN_SOCKET) {
if( shouldRedirect ){
hsh_ServerComSys.redirect(message);
}
if (hsh_Socket.count() > 0) {
if (clientID == -1) {
hsh_Socket.textAll(message);
} else {
if (hsh_Socket.availableForWrite(clientID) && hsh_Socket.hasClient(clientID)) {
hsh_Socket.text(clientID, message);
}
}
}
} else if (socket == ADMIN_SOCKET && hsh_adminSocket.count() > 0) {
if (clientID == -1) {
hsh_adminSocket.textAll(message);
} else {
if (hsh_adminSocket.availableForWrite(clientID) && hsh_adminSocket.hasClient(clientID)) {
hsh_adminSocket.text(clientID, message);
}
}
}
socketUnlock();
}
void sSystem::socketSend(JsonObject &message, int socket, size_t JsonBufferSize, int clientID, boolean shouldRedirect) {
socketLock();
char *messageString = (char *)ps_malloc(JsonBufferSize * sizeof(char));
if (messageString != NULL) {
size_t len = serializeJson(message, messageString, JsonBufferSize);
if (len > 0) {
if (socket == MAIN_SOCKET) {
if( shouldRedirect ){
hsh_ServerComSys.redirect(messageString);
}
if (hsh_Socket.count() > 0) {
if (clientID == -1) {
hsh_Socket.textAll(messageString, len);
} else {
if (hsh_Socket.availableForWrite(clientID) && hsh_Socket.hasClient(clientID)) {
hsh_Socket.text(clientID, messageString, len);
}
}
}
} else if (socket == ADMIN_SOCKET && hsh_adminSocket.count() > 0) {
if (clientID == -1) {
hsh_adminSocket.textAll(messageString, len);
} else {
if (hsh_adminSocket.availableForWrite(clientID) && hsh_adminSocket.hasClient(clientID)) {
hsh_adminSocket.text(clientID, messageString, len);
}
}
}
} else {
#if SS_DEBUG_MODE
Serial.println("Socket message empty");
#endif
}
free(messageString);
}
socketUnlock();
}
In every case, the message string pointer is allocated on external RAM which is 4mb. There is no way it could overflow even if it was not freed since my entire application uses like 500kb from the external ram.
EDIT END
Nothing fancy going on. The free heap is constatnly at 100-130kb. So that can not be a problem.
Can anyone help me here?
Random crash at runtime again.
CORRUPT HEAP: Bad head at 0x3ffeb398. Expected 0xabba1234 got 0x3ffe4364
assert failed: multi_heap_free multi_heap_poisoning.c:253 (head != NULL)
Backtrace:0x40083e1d:0x3ffb25500x4008edc5:0x3ffb2570 0x40094521:0x3ffb2590 0x40094167:0x3ffb26c0 0x400842b1:0x3ffb26e0 0x40094551:0x3ffb2700 0x401907b9:0x3ffb2720 0x401936f4:0x3ffb2740 0x400f367d:0x3ffb2760 0x401ab2a3:0x3ffb2780 0x400f46d2:0x3ffb27a0 0x400f29cd:0x3ffb27c0 0x400d2bf6:0x3ffb27e0 0x400d2976:0x3ffb2800 0x4010a415:0x3ffb2820
#0 0x40083e1d:0x3ffb25500 in panic_abort at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/esp_system/panic.c:402
DECODED:
0x40083e1d: panic_abort at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/esp_system/panic.c line 402
0x4008edc5: esp_system_abort at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/esp_system/esp_system.c line 128
0x40094521: __assert_func at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/newlib/assert.c line 85
0x40094167: multi_heap_free at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/heap/multi_heap_poisoning.c line 245
0x400842b1: heap_caps_free at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/heap/heap_caps.c line 340
0x40094551: free at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/newlib/heap.c line 39
0x401907b9: read_encoded_value_with_base(unsigned char, _Unwind_Ptr, unsigned char const*, _Unwind_Ptr*) at /builds/idf/crosstool-NG/.build/HOST-x86_64-w64-mingw32/xtensa-esp32-elf/src/gcc/libstdc++-v3/../libgcc/unwind-pe.h line 207
0x401936f4: std::__shared_ptr ::reset (WiFiClientSocketHandle*) at c:\users\pc\.platformio\packages\toolchain-xtensa-esp32\xtensa-esp32-elf\include\c++\8.4.0\bits/shared_ptr_base.h line 372
0x400f367d: WebSocketsClient::clientDisconnect(WSclient_t*) at lib/arduinoWebSockets/src/WebSocketsClient.cpp line 507
0x401ab2a3: TLSTraits::~TLSTraits() at C:/Users/Pc/.platformio/packages/framework-arduinoespressif32/libraries/HTTPClient/src/HTTPClient.cpp line 49
0x400f46d2: WebSocketsClient::loop() at lib/arduinoWebSockets/src/WebSocketsClient.cpp line 215
0x400f29cd: SocketIOclient::loop() at lib/arduinoWebSockets/src/SocketIOclient.cpp line 177
0x400d2bf6: serverCommSys::loop() at src/utilities/HsHServerComm.cpp line 109
0x400d2976: loop() at src/main.cpp line 102
0x4010a415: app_main() at C:/Users/Pc/.platformio/packages/framework-arduinoespressif32/cores/esp32/main.cpp line 70