boblemaire / asyncHTTPrequest

asynchronous HTTP for ESP using ESPasyncTCP. Works like XMLHTTPrequest in JS.
GNU General Public License v3.0
64 stars 31 forks source link

ESP32 crashes when making simultaneous requests with 2 instances #23

Closed joaolrc closed 4 years ago

joaolrc commented 4 years ago

So im making a project that needs to deal with 2 simultaneous requests so i have created 2 instances of asyncHTTPrequest and i call one per request i need to do. Example code below:

void CountinoWebConfig::publishCounts2(counterData_t counterData){
    //retrieve last counter data formatted
    String lastCounterData = formatData(counterData.sequenceNum, myTimeTracker.getLocalUnixTimeString(), counterData.periodDurationMs, counterData.countsInThisPeriod,counterData.totalCounts, counterData.minCountsPerSecondInThisPeriod, counterData.maxCountsPerSecondInThisPeriod);
    //insert data in buffer if space available
    if ( myConfigFromPortal.UploadAPI != (char*)"" ){
        if (_requestBuffer_Counter < CWC_REQUESTBUFFERLEN){
            _requestBuffer[_requestBuffer_Counter] = lastCounterData;
            _requestBuffer_Counter++;
        }

        //append previous buffered reccords
        String allData = "";
        for (uint16_t i= 0 ; i<_requestBuffer_Counter; i++){
            if (i==0){
                allData += _requestBuffer[i];
            }else{
                allData+=','+_requestBuffer[i];
            }
        }

        String dataToSend = getJSON(allData);   //jsonify data     

        if (_hasConnectivity && ! _isPublishing){
            Serial.print("[CountinoWebConfig] Will Send POST\n");
            _isPublishing = true;
            request.setDebug(true);

            //prepare request callback
            request.onReadyStateChange([this](void* optParm, asyncHTTPrequest* request, int readyState){
                if(readyState == 4){
                    int httpCode = request->responseHTTPcode();
                    Serial.printf("[CountinoWebConfig] HTTP response text : %s\n", request->responseText().c_str());
                    Serial.printf("[CountinoWebConfig] HTTP CODE is: %d\n ", httpCode );
                    if (httpCode == 200){
                        signalPortalPushSuccess(true);
                        _requestBufferCustomUrl_Counter=0;
                    }else{
                        signalPortalPushSuccess(false);
                    }
                    request->setDebug(false);
                    _isPublishing = false;
                }
            });
            //send request
            if(request.readyState() == 0 || request.readyState() == 4){
                request.open("POST", myConfigFromPortal.UploadAPI.c_str());
                request.setReqHeader("Connection", "close");
                request.setReqHeader("Content-Type", "application/json");
                request.setReqHeader("Content-Length", String(dataToSend.length()).c_str());
                request.send(dataToSend);
            }
        }else{
            signalPortalPushSuccess(false);
        }
    }

    //Do the same for custom portal
    //insert data in buffer if space available
    if ( myConfigFromPortal.data_destination_detail != (char*)"" ){
        if (_requestBufferCustomUrl_Counter < CWC_REQUESTBUFFERLEN){
            _requestBufferCustomUrl[_requestBufferCustomUrl_Counter] = lastCounterData;
            _requestBufferCustomUrl_Counter++;
        }

        //append previous buffered reccords
        String allData = "";
        for (uint16_t i= 0 ; i<_requestBufferCustomUrl_Counter; i++){
            if (i==0){
                allData += _requestBufferCustomUrl[i];
            }else{
                allData+=','+_requestBufferCustomUrl[i];
            }

        }
        String dataToSend = getJSON(allData); //jsonify data       

        if (_hasConnectivity && !_isPublishingCustom){
            Serial.print("[CountinoWebConfig] Will Send POST to Custom URL\n");
            _isPublishingCustom = true;
            requestCustom.setDebug(true);

            requestCustom.onReadyStateChange([this](void* optParm, asyncHTTPrequest* requestCust, int readyState){
                if(readyState == 4){
                    int httpCode = requestCust->responseHTTPcode();
                    Serial.printf("[CountinoWebConfig] HTTP response text : %s\n", requestCust->responseText().c_str());
                    Serial.printf("[CountinoWebConfig] HTTP CODE is: %d\n ", httpCode );
                    if (httpCode == 200){
                        signalCustomPortalPushSuccess(true);
                        _requestBufferCustomUrl_Counter=0;
                    }else{
                        signalCustomPortalPushSuccess(false);
                    }
                    requestCust->setDebug(false);
                    _isPublishingCustom = false;
                }
            });

            if(requestCustom.readyState() == 0 || requestCustom.readyState() == 4){
                requestCustom.open("POST", myConfigFromPortal.data_destination_detail.c_str());
                requestCustom.setReqHeader("Connection", "close");
                requestCustom.setReqHeader("Content-Type", "application/json");
                requestCustom.setReqHeader("Content-Length", String(dataToSend.length()).c_str());
                requestCustom.send(dataToSend);
            }
        }else{
            signalCustomPortalPushSuccess(false);
        }
    }
}

/////////////////////////// OUTPUT /////////////////////

[PulseCounterEnhanced] Will Do publish
[TimeTracker] UTC: 1590402409[CountinoWebConfig] Will Send POST
Debug(60011): setDebug(on) version 1.1.15
Debug(60015): open(POST, http://wifi-counter.cloud/backen)
Debug(  0): _parseURL() HTTP://wifi-counter.cloud:80/backend/api/admin/add_record/
Debug(  8): _connect()
Debug( 14): send(String) {
 "regId" : "$1... (81)
Debug( 15): _buildRequest()
Debug( 17): _send() 225
Debug( 19): *can't send
[CountinoWebConfig] Will Send POST to Custom URL
Debug(60045): setDebug(on) version 1.1.15
Debug(60049): open(POST, http://192.168.1.238:8080)
Debug(  0): send(String) {
 "regId" : "$1... (81)
Debug(  5): _buildRequest()
Guru Meditation Error: Core  1 panic'ed (LoadProhibited). Exception was unhandled.
Core 1 register dump:
PC      : 0x400014fd  PS      : 0x00060e30  A0      : 0x800df248  A1      : 0x3ffb1c40  
A2      : 0x00000000  A3      : 0xfffffffc  A4      : 0x000000ff  A5      : 0x0000ff00  
A6      : 0x00ff0000  A7      : 0xff000000  A8      : 0x00000000  A9      : 0x0000003b  
A10     : 0x00000005  A11     : 0x3f40330f  A12     : 0x00000005  A13     : 0x3ffd59c4  
A14     : 0x00000020  A15     : 0x2054534f  SAR     : 0x00000018  EXCCAUSE: 0x0000001c  
EXCVADDR: 0x00000000  LBEG    : 0x400014fd  LEND    : 0x4000150d  LCOUNT  : 0xffffffff  

Backtrace: 0x400014fd:0x3ffb1c40 0x400df245:0x3ffb1c50 0x400de1a9:0x3ffb1c70 0x400de9a2:0x3ffb1c90 0x400e3382:0x3ffb1cc0 0x400d1716:0x3ffb1d80 0x400e497d:0x3ffb1e00 0x400d1963:0x3ffb1f90 0x400e6cad:0x3ffb1fb0 0x40088c99:0x3ffb1fd0

Rebooting...
ets Jun  8 2016 00:22:57

rst:0xc (SW_CPU_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
configsip: 0, SPIWP:0xee
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
mode:DIO, clock div:2
load:0x3fff0018,len:4
load:0x3fff001c,len:1044
load:0x40078000,len:8896
load:0x40080400,len:5828
entry 0x400806ac

Not sure if im making anything wrong or its the library not handling properly the soimultaneous requests. I did a similar library before but changed to this one because it felt more complete. Help is much appreciated please!

joaolrc commented 4 years ago

OK i noticed that if there is no forward slash at the end of the URL, it crashes. I was posting to my local server --> "http://192.168.1.238:8080" and it was missing the ... slash --> 8080/

boblemaire commented 4 years ago

I think if you checked the boolean return from request.open it would have been false. That said, the subsequent send on the unopened request needs to be bulletproofed, and I'll do so next time I'm working on it. Thanks.

joaolrc commented 4 years ago

Thanks so much for the quick response. didnt notice that request.open returns boolean. I will protect that but still it was my fault on the forward slash. Good job on this library. Until now, its working very well but if you want to make it perfect --> HTTPS support :)