Closed zekageri closed 2 years ago
Possibly relevant: the AsyncWebServerRequest::beginResponse() method that receives the template processor callback expects a callback method signature of the form:
typedef std::function<String(const String&)> AwsTemplateProcessor;
Your method has this signature instead: char* mainPageTemplateProcessor (const String &)
. Let's just hope the std::function template is smart enough to recognize the return type of the actual function and attempt to cast the char* to String, otherwise bad things might happen.
Additionally, your mainPageTemplateProcessor
function has several paths by which it returns (char *)0, which the architecture probably interprets as NULL. From what I examined in the WString.cpp
code, using the String
object with a char* pointer that happens to be NULL will result in an internal NULL (not zero-length) buffer. Using the copy constructor of such a NULL String
will propagate the NULL to the copied String
object. With such an object, the WString::c_str()
method will return NULL. And the template processing code contains a memcpy()
with the source ptr returned from the WString::c_str()
method without further validation...
Might be better to change the template processor signature, and make it return a constant empty string, not NULL, where appropiate, then try to trigger the issue again.
Oh god. Thank you for the info. I did thought about that. I was about to make the function to return an error json string instead of 0. I will adjust my code.
Appreciate the help! I hope it will fix it
Yeah it looks like the problem was the char return. I made the function back to String and cast every char to String before returning. It seems to work. I will test it now. Thank you for your help.
Sorry i had to reopen this. It still can happen with this template processor:
inline String mainPageTemplateProcessor(const String& var){
if( var == "LAN_OB" ){
getLangFile();
return String(currentLangFile);
}else if(var == "CONF_D"){
if(hasConfig){
return String(configString);
}
}else if( var == "USR_D"){
if(isThereUserFile){
return String(usersString);
}
}else if( var == "USER_ZONES" ){
if(hasZones){
return String(zonesBuffer);
}
}
return "";
}
The thing is that all my buffers are char pointers, allocated in external ram. Should i copy it to a local String before returning it? Something like this:
inline String mainPageTemplateProcessor(const String& var){
String buffer = "";
if( var == "LAN_OB" ){
getLangFile();
// buffer = currentLangFile.toString();
// buffer(currentLangFile);
buffer = String(currentLangFile);
//return String(currentLangFile);
}else if(var == "CONF_D"){
if(hasConfig){
// buffer = configString.toString();
// buffer(configString);
buffer = String(configString);
//return String(configString);
}
}else if( var == "USR_D"){
if(isThereUserFile){
// buffer = usersString.toString();
// buffer(usersString);
buffer = String(usersString);
//return String(usersString);
}
}else if( var == "USER_ZONES" ){
if(hasZones){
// buffer = zonesBuffer.toString();
// buffer(zonesBuffer);
buffer = String(zonesBuffer);
//return String(zonesBuffer);
}
}
return buffer;
}
Guru Meditation Error: Core 0 panic'ed (LoadProhibited). Exception was unhandled.
Core 0 register dump:
PC : 0x4008e2c6 PS : 0x00060530 A0 : 0x800db64c A1
: 0x3ffde080
A2 : 0x3f80c385 A3 : 0x00000000 A4 : 0x0001869f A5
: 0x00000074
A6 : 0x00000001 A7 : 0x3ffda460 A8 : 0x00000001 A9
: 0x00000000
A10 : 0x3ffde10c A11 : 0x3ffde10c A12 : 0x3ffde10c A13
: 0x3ffde100
A14 : 0x3ffde400 A15 : 0x3fa0e134 SAR : 0x00000010 EXCCAUSE: 0x0000001c
EXCVADDR: 0x00000000 LBEG : 0x4008c9b8 LEND : 0x4008c9d4 LCOUNT
: 0x00000000
ELF file SHA256: 0000000000000000
Backtrace: 0x4008e2c6:0x3ffde080 0x400db649:0x3ffde0a0 0x401addd9:0x3ffde1a0 0x400f4518:0x3ffde1c0 0x400f47c5:0x3ffde250 0x400f037e:0x3ffde2a0 0x400f03a1:0x3ffde2c0 0x4018331e:0x3ffde2e0 0x40183d95:0x3ffde310 0x40182dd1:0x3ffde370 0x400907fa:0x3ffde3c0
#0 0x4008e2c6:0x3ffde080 in strlcpy at /home/mak/e/p/newlib_old/newlib_xtensa-bin/newlib_xtensa-2.2.0/xtensa-esp32-elf/newlib/libc/string/../../../.././newlib/libc/string/strlcpy.c:55
#1 0x400db649:0x3ffde0a0 in mainPageTemplateProcessor(String const&) at lib/ArduinoJson-6.x/src/ArduinoJson/Json/JsonDeserializer.hpp:58
(inlined by) mainPageTemplateProcessor(String const&) at src/headers/authenticator.h:7
#2 0x401addd9:0x3ffde1a0 in std::_Function_handler<String (String const&), String (*)(String const&)>::_M_invoke(std::_Any_data const&, String const&) at lib/ArduinoJson-6.x/src/ArduinoJson/Json/JsonDeserializer.hpp:58
#3 0x400f4518:0x3ffde1c0 in std::function<String (String const&)>::operator()(String const&) const at lib\ESPAsyncWebServer-yuboxfixes-0xFEEDC0DE64-cleanup\src/WebResponses.cpp:700
(inlined by) AsyncAbstractResponse::_fillBufferAndProcessTemplates(unsigned char*, unsigned int) at lib\ESPAsyncWebServer-yuboxfixes-0xFEEDC0DE64-cleanup\src/WebResponses.cpp:442
#4 0x400f47c5:0x3ffde250 in AsyncAbstractResponse::_ack(AsyncWebServerRequest*, unsigned int, unsigned int) at lib\ESPAsyncWebServer-yuboxfixes-0xFEEDC0DE64-cleanup\src/WebResponses.cpp:700
#5 0x400f037e:0x3ffde2a0 in AsyncWebServerRequest::_onAck(unsigned int, unsigned int) at lib\ESPAsyncWebServer-yuboxfixes-0xFEEDC0DE64-cleanup\src/WebRequest.cpp:814
#6 0x400f03a1:0x3ffde2c0 in std::_Function_handler<void (void*, AsyncClient*, unsigned int, unsigned int), AsyncWebServerRequest::AsyncWebServerRequest(AsyncWebServer*, AsyncClient*)::{lambda(void*, AsyncClient*, unsigned int, unsigned int)#3}>::_M_invoke(std::_Any_data const&, void*&&, AsyncClient*&&, unsigned int&&, AsyncClient*&&) at lib\ESPAsyncWebServer-yuboxfixes-0xFEEDC0DE64-cleanup\src/WebRequest.cpp:814
(inlined by) _M_invoke at c:\users\pc\.platformio\packages\toolchain-xtensa32@2.50200.97\xtensa-esp32-elf\include\c++\5.2.0/functional:1871
#7 0x4018331e:0x3ffde2e0 in std::function<void (void*, AsyncClient*, unsigned int, unsigned int)>::operator()(void*, AsyncClient*, unsigned int,
unsigned int) const at lib\AsyncTCPSock\src/AsyncTCP.cpp:360
(inlined by) AsyncClient::_notifyWrittenBuffers(std::deque<AsyncClient::notify_writebuf, std::allocator<AsyncClient::notify_writebuf> >&, int) at lib\AsyncTCPSock\src/AsyncTCP.cpp:840
#8 0x40183d95:0x3ffde310 in AsyncClient::_sockIsWriteable() at lib\AsyncTCPSock\src/AsyncTCP.cpp:360
#9 0x40182dd1:0x3ffde370 in _asynctcpsock_task(void*) at lib\AsyncTCPSock\src/AsyncTCP.cpp:360
#10 0x400907fa:0x3ffde3c0 in vPortTaskWrapper at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/freertos/port.c:355 (discriminator 1)
Rebooting...
authentication response sent
Current free heap: 132328
Current free heap: 140316
Current free heap: 109172
authentication response sent
Current free heap: 138896
abort() was called at PC 0x4017f903 on core 0
ELF file SHA256: 0000000000000000
Backtrace: 0x4008f57c:0x3ffdd2c0 0x4008f7f5:0x3ffdd2e0 0x4017f903:0x3ffdd300 0x4017f94a:0x3ffdd320 0x4017f023:0x3ffdd340 0x4017f35a:0x3ffdd360 0x400f4282:0x3ffdd380 0x400f4675:0x3ffdd3b0 0x400f4875:0x3ffdd440 0x400f042e:0x3ffdd490 0x400f0451:0x3ffdd4b0 0x401833ce:0x3ffdd4d0 0x40183e45:0x3ffdd500 0x40182e81:0x3ffdd560 0x400907fa:0x3ffdd5b0
#0 0x4008f57c:0x3ffdd2c0 in invoke_abort at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/esp32/panic.c:715
#1 0x4008f7f5:0x3ffdd2e0 in abort at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/esp32/panic.c:715
#2 0x4017f903:0x3ffdd300 in __cxxabiv1::__terminate(void (*)()) at /builds/idf/crosstool-NG/.build/src/gcc-5.2.0/libstdc++-v3/libsupc++/eh_terminate.cc:112
#3 0x4017f94a:0x3ffdd320 in std::terminate() at /builds/idf/crosstool-NG/.build/src/gcc-5.2.0/libstdc++-v3/libsupc++/eh_terminate.cc:112
#4 0x4017f023:0x3ffdd340 in __cxa_throw at /builds/idf/crosstool-NG/.build/src/gcc-5.2.0/libstdc++-v3/libsupc++/eh_throw.cc:87
#5 0x4017f35a:0x3ffdd360 in operator new(unsigned int) at /builds/idf/crosstool-NG/.build/src/gcc-5.2.0/libstdc++-v3/libsupc++/new_op.cc:54
#6 0x400f4282:0x3ffdd380 in __gnu_cxx::new_allocator<unsigned char>::allocate(unsigned int, void const*) at lib\ESPAsyncWebServer-yuboxfixes-0xFEEDC0DE64-cleanup\src/WebResponses.cpp:700
(inlined by) std::allocator_traits<std::allocator<unsigned char> >::allocate(std::allocator<unsigned char>&, unsigned int) at c:\users\pc\.platformio\packages\toolchain-xtensa32@2.50200.97\xtensa-esp32-elf\include\c++\5.2.0\bits/alloc_traits.h:360
(inlined by) std::_Vector_base<unsigned char, std::allocator<unsigned char> >::_M_allocate(unsigned int) at c:\users\pc\.platformio\packages\toolchain-xtensa32@2.50200.97\xtensa-esp32-elf\include\c++\5.2.0\bits/stl_vector.h:170
(inlined by) void std::vector<unsigned char, std::allocator<unsigned char> >::_M_range_insert<char const*>(__gnu_cxx::__normal_iterator<unsigned char*, std::vector<unsigned char, std::allocator<unsigned char> > >, char const*, char const*, std::forward_iterator_tag) at c:\users\pc\.platformio\packages\toolchain-xtensa32@2.50200.97\xtensa-esp32-elf\include\c++\5.2.0\bits/vector.tcc:659
#7 0x400f4675:0x3ffdd3b0 in void std::vector<unsigned char, std::allocator<unsigned char> >::_M_insert_dispatch<char const*>(__gnu_cxx::__normal_iterator<unsigned char*, std::vector<unsigned char, std::allocator<unsigned char> > >, char const*, char const*, std::__false_type) at lib\ESPAsyncWebServer-yuboxfixes-0xFEEDC0DE64-cleanup\src/WebResponses.cpp:700
(inlined by) __gnu_cxx::__normal_iterator<unsigned char*, std::vector<unsigned char, std::allocator<unsigned char> > > std::vector<unsigned char, std::allocator<unsigned char> >::insert<char const*, void>(__gnu_cxx::__normal_iterator<unsigned char const*, std::vector<unsigned char, std::allocator<unsigned char> > >, char const*, char const*) at c:\users\pc\.platformio\packages\toolchain-xtensa32@2.50200.97\xtensa-esp32-elf\include\c++\5.2.0\bits/stl_vector.h:1099
(inlined by) AsyncAbstractResponse::_fillBufferAndProcessTemplates(unsigned char*, unsigned int) at lib\ESPAsyncWebServer-yuboxfixes-0xFEEDC0DE64-cleanup\src/WebResponses.cpp:461
#8 0x400f4875:0x3ffdd440 in AsyncAbstractResponse::_ack(AsyncWebServerRequest*, unsigned int, unsigned int) at lib\ESPAsyncWebServer-yuboxfixes-0xFEEDC0DE64-cleanup\src/WebResponses.cpp:700
#9 0x400f042e:0x3ffdd490 in AsyncWebServerRequest::_onAck(unsigned int, unsigned int) at lib\ESPAsyncWebServer-yuboxfixes-0xFEEDC0DE64-cleanup\src/WebRequest.cpp:814
#10 0x400f0451:0x3ffdd4b0 in std::_Function_handler<void (void*, AsyncClient*, unsigned int, unsigned int), AsyncWebServerRequest::AsyncWebServerRequest(AsyncWebServer*, AsyncClient*)::{lambda(void*, AsyncClient*, unsigned int, unsigned int)#3}>::_M_invoke(std::_Any_data const&, void*&&, AsyncClient*&&, unsigned int&&, AsyncClient*&&) at lib\ESPAsyncWebServer-yuboxfixes-0xFEEDC0DE64-cleanup\src/WebRequest.cpp:814
(inlined by) _M_invoke at c:\users\pc\.platformio\packages\toolchain-xtensa32@2.50200.97\xtensa-esp32-elf\include\c++\5.2.0/functional:1871
#11 0x401833ce:0x3ffdd4d0 in std::function<void (void*, AsyncClient*, unsigned int, unsigned int)>::operator()(void*, AsyncClient*, unsigned int,
unsigned int) const at lib\AsyncTCPSock\src/AsyncTCP.cpp:360
(inlined by) AsyncClient::_notifyWrittenBuffers(std::deque<AsyncClient::notify_writebuf, std::allocator<AsyncClient::notify_writebuf> >&, int) at lib\AsyncTCPSock\src/AsyncTCP.cpp:840
#12 0x40183e45:0x3ffdd500 in AsyncClient::_sockIsWriteable() at lib\AsyncTCPSock\src/AsyncTCP.cpp:360
#13 0x40182e81:0x3ffdd560 in _asynctcpsock_task(void*) at lib\AsyncTCPSock\src/AsyncTCP.cpp:360
#14 0x400907fa:0x3ffdd5b0 in vPortTaskWrapper at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/freertos/port.c:355 (discriminator 1)
Rebooting...
With this processor:
inline String mainPageTemplateProcessor(const String& var) {
String buffer = "";
if (var == "LAN_OB") {
getLangFile();
buffer = String(currentLangFile);
} else if (var == "CONF_D") {
if (hasConfig) {
buffer = String(configString);
}
} else if (var == "USR_D") {
if (isThereUserFile) {
buffer = String(usersString);
}
} else if (var == "USER_ZONES") {
if (hasZones) {
buffer = String(zonesBuffer);
}
}
return buffer;
}
Ditched the template processor. Instead the webpage rules all the relevant data via websockets.
Hi! I got the following crash
The handler function:
As you can see i got 150k free heap right before the handler executes. The Serial.prints indicates that the crash is after the
mainPageTemplateProcessor
function returns the last variable. In 40% of the cases the webpage loading really fast, revealing all the variables from template processor and they are valid variables. If one of them is empty, i protect it with some boolean variables. The semaphore also takes care about the reads and writes from other functions. ( no other core uses these variables. everything runs on core 1 for me and a modbus communication on core 0 which has nothing to do with these variables )What can cause the problem? Thank you in advance.