Skip to content

Error on page request with captive portal #7

@zekageri

Description

@zekageri

If the ESP is in STA mode, everything works fine. If i use it with it's AP mode and captive request handler it crashes sometimes on page load.

Here is the decoded trace:

CORRUPT HEAP: Bad head at 0x3ffd89f8. Expected 0xabba1234 got 0x00000000

assert failed: multi_heap_free multi_heap_poisoning.c:253 (head != NULL)


Backtrace:0x40083cbd:0x3ffd81100x4008ece5:0x3ffd8130 0x400944d9:0x3ffd8150 0x4009411f:0x3ffd8280 0x40084151:0x3ffd82a0 0x40094509:0x3ffd82c0 0x4010d9a5:0x3ffd82e0 0x4010d9b5:0x3ffd8300 0x40101ecb:0x3ffd8320 0x40101ef1:0x3ffd8340 0x401014f2:0x3ffd8360 0x4010388d:0x3ffd8380 0x400fea63:0x3ffd83a0 0x400fea71:0x3ffd83c0 0x4019e691:0x3ffd83e0 0x4019e99e:0x3ffd8410 0x4019e9b4:0x3ffd8430 0x4019ead6:0x3ffd8450

  #0  0x40083cbd:0x3ffd8110 in panic_abort at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/esp_system/panic.c:402
  #1  0x4008ece5:0x3ffd8130 in esp_system_abort at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/esp_system/esp_system.c:128
  #2  0x400944d9:0x3ffd8150 in __assert_func at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/newlib/assert.c:85
  #3  0x4009411f:0x3ffd8280 in multi_heap_free at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/heap/multi_heap_poisoning.c:253
      (inlined by) multi_heap_free at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/heap/multi_heap_poisoning.c:245
  #4  0x40084151:0x3ffd82a0 in heap_caps_free at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/heap/heap_caps.c:340
  #5  0x40094509:0x3ffd82c0 in free at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/newlib/heap.c:39
  #6  0x4010d9a5:0x3ffd82e0 in String::invalidate() at C:/Users/Pc/.platformio/packages/framework-arduinoespressif32/cores/esp32/WString.cpp:175
  #7  0x4010d9b5:0x3ffd8300 in String::~String() at C:/Users/Pc/.platformio/packages/framework-arduinoespressif32/cores/esp32/WString.cpp:159
  #8  0x40101ecb:0x3ffd8320 in AsyncFileResponse::~AsyncFileResponse() at lib/ESPAsyncWebServer-yuboxfixes-0xFEEDC0DE64-cleanup/src/WebResponses.cpp:481
  #9  0x40101ef1:0x3ffd8340 in AsyncFileResponse::~AsyncFileResponse() at lib/ESPAsyncWebServer-yuboxfixes-0xFEEDC0DE64-cleanup/src/WebResponses.cpp:484
  #10 0x401014f2:0x3ffd8360 in AsyncWebServerRequest::~AsyncWebServerRequest() at lib/ESPAsyncWebServer-yuboxfixes-0xFEEDC0DE64-cleanup/src/WebRequest.cpp:85 (discriminator 1)
  #11 0x4010388d:0x3ffd8380 in AsyncWebServer::_handleDisconnect(AsyncWebServerRequest*) at lib/ESPAsyncWebServer-yuboxfixes-0xFEEDC0DE64-cleanup/src/WebServer.cpp:107 (discriminator 1)
  #12 0x400fea63:0x3ffd83a0 in AsyncWebServerRequest::_onDisconnect() at lib/ESPAsyncWebServer-yuboxfixes-0xFEEDC0DE64-cleanup/src/WebRequest.cpp:248
  #13 0x400fea71:0x3ffd83c0 in std::_Function_handler<void (void*, AsyncClient*), AsyncWebServerRequest::AsyncWebServerRequest(AsyncWebServer*, AsyncClient*)::{lambda(void*, AsyncClient*)#4}>::_M_invoke(std::_Any_data 
const&, void*&&, AsyncClient*&&) at lib/ESPAsyncWebServer-yuboxfixes-0xFEEDC0DE64-cleanup/src/WebRequest.cpp:70
      (inlined by) _M_invoke at c:\users\pc\.platformio\packages\toolchain-xtensa-esp32\xtensa-esp32-elf\include\c++\8.4.0\bits/std_function.h:297
  #14 0x4019e691:0x3ffd83e0 in std::function<void (void*, AsyncClient*)>::operator()(void*, AsyncClient*) const at c:\users\pc\.platformio\packages\toolchain-xtensa-esp32\xtensa-esp32-elf\include\c++\8.4.0\bits/std_function.h:687
  #15 0x4019e99e:0x3ffd8410 in AsyncClient::_fin(tcp_pcb*, signed char) at lib/AsyncTCP-master/src/AsyncTCP.cpp:908
      (inlined by) AsyncClient::_fin(tcp_pcb*, signed char) at lib/AsyncTCP-master/src/AsyncTCP.cpp:905      
  #16 0x4019e9b4:0x3ffd8430 in AsyncClient::_s_fin(void*, tcp_pcb*, signed char) at lib/AsyncTCP-master/src/AsyncTCP.cpp:1215
  #17 0x4019ead6:0x3ffd8450 in _async_service_task(void*) at lib/AsyncTCP-master/src/AsyncTCP.cpp:166        
      (inlined by) _async_service_task at lib/AsyncTCP-master/src/AsyncTCP.cpp:198




ELF file SHA256: 0000000000000000

Here is the request handler

class CaptiveRequestHandler : public AsyncWebHandler {
    bootHandler *handler;
    public:
        CaptiveRequestHandler() {
            captiveSerer.serveStatic("/", LittleFS, ASSETS_PATH).setCacheControl(MAX_CACHE_CONTROL_TIME);
            
            captiveSerer.on("/welcome.bundle.css", HTTP_GET, [this](AsyncWebServerRequest *request) {
                String path = fileSys.correctPath(WELCOME_PAGE_CSS_PATH);
                AsyncWebServerResponse *response = request->beginResponse(LittleFS, path, getMimeType(path));
                response->addHeader("Server", "HsH Server");
                if( path.indexOf("zipped") > 0 ){
                    response->addHeader("Content-Encoding", "gzip");
                }
                request->send(response);
            });

            captiveSerer.on("/welcome.bundle.js", HTTP_GET, [this](AsyncWebServerRequest *request) {
                String path = fileSys.correctPath(WELCOME_PAGE_JS_PATH);
                AsyncWebServerResponse *response = request->beginResponse(LittleFS, path, getMimeType(path));
                response->addHeader("Server", "HsH Server");
                if( path.indexOf("zipped") > 0 ){
                    response->addHeader("Content-Encoding", "gzip");
                }
                request->send(response);
            });

            captiveSerer.on("/summaryEnd", HTTP_POST, [this](AsyncWebServerRequest *request) {
                AsyncWebParameter* p = request->getParam(0);
                handler->handleConfig( p->value() );
                request->send(200, "text/plain", "OK");
            });
        
            /* NOT FOUND HANDLERS */
            captiveSerer.on("/notFound.css", HTTP_GET, [this](AsyncWebServerRequest *request) {
                String path = fileSys.correctPath(NOT_FOUND_STYLE_PATH);
                AsyncWebServerResponse *response = request->beginResponse(LittleFS, path, getMimeType(path));
                response->addHeader("Server", "HsH Server");
                if( path.indexOf("zipped") > 0 ){
                    response->addHeader("Content-Encoding", "gzip");
                }
                request->send(response);
            });

            captiveSerer.on("/notFound.js", HTTP_GET, [this](AsyncWebServerRequest *request) {
                String path = fileSys.correctPath(NOT_FOUND_SCRIPT_PATH);
                AsyncWebServerResponse *response = request->beginResponse(LittleFS, path, getMimeType(path));
                response->addHeader("Server", "HsH Server");
                if( path.indexOf("zipped") > 0 ){
                    response->addHeader("Content-Encoding", "gzip");
                }
                request->send(response);
            });

            captiveSerer.onNotFound([this](AsyncWebServerRequest *request) {
                String path = fileSys.correctPath(NOT_FOUND_PATH);
                AsyncWebServerResponse *response = request->beginResponse(LittleFS, path, getMimeType(path));
                response->addHeader("Server", "HsH Server");
                if( path.indexOf("zipped") > 0 ){
                    response->addHeader("Content-Encoding", "gzip");
                }
                request->send(response);
            });
        }

        virtual ~CaptiveRequestHandler() {}

        bool canHandle(AsyncWebServerRequest *request){
            //request->addInterestingHeader("ANY");
            return true;
        }

        void handleRequest(AsyncWebServerRequest *request) {
            String path = fileSys.correctPath(WELCOME_PAGE_PATH);
            AsyncWebServerResponse *response = request->beginResponse(LittleFS, path, "text/html");
            response->addHeader("Server", "HsH Setup");
            if( path.indexOf("zipped") > 0 ){
                response->addHeader("Content-Encoding", "gzip");
            }
            request->send(response);
        }
};

Here is how it is inited:

void bootHandler::initAP(){
    WiFi.softAPConfig(apIP, apIP, netMsk);
    WiFi.softAP(firstBootAP_NAME);
    dnsServer.start(53, "*", WiFi.softAPIP());
    IPAddress myIP = WiFi.softAPIP();
    Serial.print("AP IP address: ");
    Serial.println(myIP);
}

void bootHandler::initServer(){
    captiveSerer.addHandler(new CaptiveRequestHandler()).setFilter(ON_AP_FILTER);
    captiveSerer.begin();
}

void bootHandler::setup(){
    Serial.println("First boot handling started...");
    initAP();
    initServer();
}

And in the loop there is only the dnsServer request processor for the captive portal

void bootHandler::loop(){
    dnsServer.processNextRequest();
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions