Skip to content

Unhandled C++ exception: OOM when used ESPhttpUpdate.update in the versions boards 3.1.2 and 3.1.1 for OTA update #8981

Open
@giselybelloadur

Description

@giselybelloadur

Basic Infos

  • [x ] This issue complies with the issue POLICY doc.
  • [x ] I have read the documentation at readthedocs and the issue is not addressed there.
  • [x ] I have tested that the issue is present in current master branch (aka latest git).
  • [x ] I have searched the issue tracker for a similar issue.
  • [x ] If there is a stack dump, I have decoded it.
  • [x ] I have filled out all fields below.

Platform

  • Hardware: [ESP8285H16 - 2M ]
  • Core Version: [3.1.2]
  • Development Env: [Arduino IDE]
  • Operating System: [Windows 10]

Settings in IDE

  • Module: [Generic ESP8285 Module]
  • Flash Mode: [dout]
  • Flash Size: [2MB(FS:64KB OTA:~992KB)]
  • lwip Variant: [v2 Lower Memory]
  • Reset Method: [dtr|nodemcu]
  • Flash Frequency: [40Mhz]
  • CPU Frequency: [80Mhz|160MHz]
  • Upload Using: [SERIAL]
  • Upload Speed: [115200] (serial upload only)

Problem Description

I have been using the esp8285 in a commercial project for a few years now and have always updated the firmware OTA. However, after flashing the esp8285 with firmware in board version 3.1.2, it is no longer possible to update the firmware over OTA. The error below occurs:

 User exception (panic/abort/assert)
 --------------- CUT HERE FOR EXCEPTION DECODER ---------------
 
 Unhandled C++ exception: OOM

 >>>stack>>>
 
 ctx: cont
 sp: 3ffffc90 end: 3fffffd0 offset: 0010
 3ffffca0:  3ffe9540 4020c3d4 00000010 4022883c  
 3ffffcb0:  3fff0704 4010bd94 3ffffd20 4020c380  
.... etc

last failed alloc call: 4020CF84(16)

--------------- CUT HERE FOR EXCEPTION DECODER ---------------

last failed alloc caller: 0x4020cf84

If you downgrade to version 3.1.0 and earlier, this error does not happen, and the firmware update via OTA proceeds normally.

There are hundreds of devices installed with board version 3.1.2 and now I can't update them over OTA anymore. Please help me to resolve. What to do?

#include <ESP8266WiFi.h>
#include <WiFiClientSecure.h>
#include <ESP8266httpUpdate.h>

void FirmwareUpdate(String URL_fw_Bin)
{ 
    #if(DEBUG_PRINT==1)
      Serial.println("New firmware detected");
    #endif
    WiFiClient client;
    BearSSL::WiFiClientSecure UpdateClient;
    UpdateClient.setInsecure();
    
   ESPhttpUpdate.setLedPin(LED_STATUS, LOW);
    
    #if(DEBUG_PRINT==1)
      Serial.print("firmware");
      Serial.println(URL_fw_Bin);
    #endif
 
    t_httpUpdate_return ret = ESPhttpUpdate.update(UpdateClient,URL_fw_Bin);

    #if(DEBUG_PRINT==1)
      switch (ret) {
        case HTTP_UPDATE_FAILED:
          Serial.printf("HTTP_UPDATE_FAILED Error (%d): %s\n", ESPhttpUpdate.getLastError(), ESPhttpUpdate.getLastErrorString().c_str());
          break;
  
        case HTTP_UPDATE_NO_UPDATES:
          Serial.println("HTTP_UPDATE_NO_UPDATES");
          break;
  
        case HTTP_UPDATE_OK:
          Serial.println("HTTP_UPDATE_OK");
          break;
      }
    #endif 
 }

Activity

mcspr

mcspr commented on Sep 2, 2023

@mcspr
Collaborator

Figure out the place where OOM happens, as noted by the "last failed alloc call: 4020CF84(16)" line (0x4020CF84 is a memory address)

Arduino IDE 2.x tooling lacks exception decoder, see https://github.com/esp8266/Arduino/blob/master/tools/decoder.py
Arduino IDE 1.x, follow our docs at https://arduino-esp8266.readthedocs.io/en/latest/faq/a02-my-esp-crashes.html#exception-decoder

I don't see anything suspicious between 3.1.0 and 3.1.2 related to memory management that might've caused this, you'd have to be more thorough when comparing our versions and / or your code :/

giselybelloadur

giselybelloadur commented on Sep 2, 2023

@giselybelloadur
Author

Hello, thanks for replying. The comparison between 3.1.0 and previous ones is because with these versions the error does not happen, only in versions 3.1.1 and 3.1.2, for the same program code, everything is the same, just changing the core version in the arduino.
Could it be the problem with BearSSL?

Unfortunately, BearSSL needs to know the buffer sizes before it begins connection, so applications that want to use smaller buffers need to check the remote server’s support before connect() .

Because TLS was developed on systems with many megabytes of memory, they require by default a 16KB buffer for receive and transmit. That's enormous for the ESP8266, which has only around 40KB total heap available.

The problem happens exactly when in this program line:

t_httpUpdate_return ret = ESPhttpUpdate.update(UpdateClient,URL_fw_Bin);

Has the buffer size changed for TLS communication in core version 3.1.2?

mcspr

mcspr commented on Sep 3, 2023

@mcspr
Collaborator

No network changes as far as I can see? Check git-log between our release tags, or from github compare page
3.1.0...3.1.2
(switching to files changed tab, '... changed files' is clickable)

It is apparent that bssl needs a lot of ram in both versions, but it had to go somewhere before that updater line is executing. Could start by checking before-and-after stats from our platform class; ESP.getFreeHeap(), ESP.getHeapStats(), etc.
Failure to alloc could've been hidden for older version for a bunch of reasons.

Another (more elaborate) way is to switch to git installation and use git-bisect to figure out what commit might've broke things between releases
https://arduino-esp8266.readthedocs.io/en/latest/installing.html#using-git-version
https://git-scm.com/docs/git-bisect

InnuendoPi

InnuendoPi commented on Oct 26, 2023

@InnuendoPi

I ve a similar problem. Maybe OOM is a result of large string allocations. see #9005
The code snippet above works fine in a small sketch. When i use the code snippet in a larger Project, i get these stats:

  • ESP8266 boot free heap before BearSSL: 26752
  • ESP8266 after boot stats free: 26752 max: 26672 frag: 1
  • ESP8266 IP Adresse: xxx Time: 16:09:40 WLAN Signal: -76
  • ESP8266 stats after BearSSL free: 20304 max: 20248 frag: 1

OOM occours regadless of MMU settings. Are there options for StreamString or reorder mem allocations readStringUntil to get BearSSL working with less than 30k heap? Same problem happens with HTTPClient GET(): server repsonse is always to large

d-a-v

d-a-v commented on Nov 4, 2023

@d-a-v
Collaborator

It is possible to reduce SSL/TLS client buffer size when peer servers allow it.
Check this example

bool mfln = client->probeMaxFragmentLength("tls.mbed.org", 443, 1024);
Serial.printf("\nConnecting to https://tls.mbed.org\n");
Serial.printf("Maximum fragment Length negotiation supported: %s\n", mfln ? "yes" : "no");
if (mfln) { client->setBufferSizes(1024, 1024); }

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

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

        Participants

        @mcspr@d-a-v@InnuendoPi@giselybelloadur

        Issue actions

          Unhandled C++ exception: OOM when used ESPhttpUpdate.update in the versions boards 3.1.2 and 3.1.1 for OTA update · Issue #8981 · esp8266/Arduino