Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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 opened this issue Sep 2, 2023 · 5 comments

Comments

@giselybelloadur
Copy link

giselybelloadur commented Sep 2, 2023

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 
 }
@mcspr
Copy link
Collaborator

mcspr commented Sep 2, 2023

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
Copy link
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
Copy link
Collaborator

mcspr commented Sep 3, 2023

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
Copy link

InnuendoPi commented Oct 26, 2023

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
Copy link
Collaborator

d-a-v commented Nov 4, 2023

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
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants