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
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions