Skip to content

ESP8266WebServer: Heap-leak and delay on aborted HTTP-requests #4892

Closed
@MagnusHelleberg

Description

@MagnusHelleberg

Basic Infos

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

Platform

  • Hardware: ESP8266EX / ESP-12E
  • Core Version: 2.4.1
  • Development Env: Visual Studio 2017 with vMicro
  • Operating System: Windows

Settings in IDE

  • Module: ESP8266MOD from AI-Thinker
  • Flash Mode: DIO
  • Flash Size: 4MB / 1MB
  • lwip Variant: v2 lower Memory
  • Reset Method: ck
  • Flash Frequency: 40Mhz
  • CPU Frequency: 160MHz
  • Upload Using: OTA

Problem Description

I have an issue with the ESP8266WebServer.
If my HTTP request is completed, everything works perfectly fine.
But if the request gets disrupted / aborted, the webserver seams to run into some kind of timeout or unhandled error.
The next request takes time to get processed (2sec. with Core 2.3.0 even longer >10s) and the free heap gets reduced every time the issue occures by 1032 bytes.

To reconstruct the issue, I wrote a simple example, where a 10KByte picture is requested via the browser.
Press the F5 key extremly fast 2 times in a row, so that the second request is faster issued than the old request is received, then the issue occures.

http://192.168.4.1/abc
Doesn't exist and so the notFound page is displayed, where the FreeHeap is shown.

Here is the .ino and the hex-dump of the picture.
webServer.zip

Hopefully I could clarify my issue.

Best regards,
Magnus.

MCVE Sketch

#include "websites.h"
#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>
#include <ESP8266HTTPUpdateServer.h>

#define ledGreen_Pin		4
#define ledRed_Pin			5

ESP8266WebServer		webServer(80);
ESP8266HTTPUpdateServer updateServer;
IPAddress				apIP(192, 168, 4, 1);

void setup()
{
	pinMode(ledGreen_Pin, OUTPUT);
	pinMode(ledRed_Pin, OUTPUT);
	digitalWrite(ledGreen_Pin, false);
	digitalWrite(ledRed_Pin, true);

	Serial.begin(115200);

	WiFi.hostname("Test123");
	WiFi.mode(WIFI_AP);
	WiFi.softAP("Test", "12345678");

	// Page not Found Handler
	webServer.onNotFound(allSites_handleUnknown);
	webServer.on("/test.jpg", sendLogo);

	// Setup the otaUpdater and register update functions to webserver
	updateServer.setup(&webServer, "/update");

	webServer.begin();

	digitalWrite(ledGreen_Pin, true);
	digitalWrite(ledRed_Pin, false);
}

void loop()
{
	webServer.handleClient();
}


// Handles all requests from files, which were not registered via webserver.on
void allSites_handleUnknown(void)
{
	String message = "File Not Found\n\n";
	message += "URI..........: ";
	message += webServer.uri();
	message += "\nMethod.....: ";
	message += (webServer.method() == HTTP_GET) ? "GET" : "POST";
	message += "\nArguments..: ";
	message += webServer.args();
	message += "\n";
	for (uint8_t i = 0; i<webServer.args(); i++) {
		message += " " + webServer.argName(i) + ": " + webServer.arg(i) + "\n";
	}
	message += "\n";
	message += "FreeHeap.....: " + String(ESP.getFreeHeap()) + "\n";
	message += "ChipID.......: " + String(ESP.getChipId()) + "\n";
	message += "FlashChipId..: " + String(ESP.getFlashChipId()) + "\n";
	message += "FlashChipSize: " + String(ESP.getFlashChipSize()) + " bytes\n";
	message += "getCycleCount: " + String(ESP.getCycleCount()) + " Cycles\n";
	message += "Milliseconds.: " + String(millis()) + " Milliseconds\n";
	webServer.send(404, "text/plain", message);
}


void sendLogo(void)
{
	webServer.send_P(200, webFiles[0].mime, webFiles[0].content, webFiles[0].len);
}
#ifndef WEBSITES_H_
#define WEBSITES_H_

//
// Website HEX-Dump
//

static const char file_0[] PROGMEM = {
  0xff, 0xd8, 0xff, 0xe0, 0x00, 0x10, 0x4a, 0x46, 0x49, 0x46, 0x00, 0x01,
  0x01, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0xff, 0xdb, 0x00, 0x84,
  0x00, 0x09, 0x06, 0x07, 0x13, 0x12, 0x12, 0x15, 0x13, 0x12, 0x13, 0x16,
  0x16, 0x15, 0x17, 0x17, 0x16, 0x15, 0x18, 0x16, 0x17, 0x18, 0x19, 0x16,
  0x17, 0x17, 0x15, 0x15, 0x15, 0x18, 0x17, 0x16, 0x17, 0x18, 0x17, 0x18,
  ...
};

struct t_websitefiles {
  const char* filename;
  const char* mime;
  const unsigned int len;
  const char* content;
} webFiles[] = {
  {
    .filename = "test.jpg",
    .mime = "image/jpeg",
    .len = 10257,
    .content = file_0
  },
};

#endif

Debug Messages

The first request is aborted from the browser and directly requested again.
The second request is delayed.

New client
method: GET url: /test.jpg search: 
headerName: Host
headerValue: 192.168.4.1
headerName: User-Agent
headerValue: Mozilla/5.0 (Windows NT 10.0; WOW64; rv:61.0) Gecko/20100101 Firefox/61.0
headerName: Accept
headerValue: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
headerName: Accept-Language
headerValue: de,en-US;q=0.7,en;q=0.3
headerName: Accept-Encoding
headerValue: gzip, deflate
headerName: Connection
headerValue: keep-alive
headerName: Upgrade-Insecure-Requests
headerValue: 1
headerName: Cache-Control
headerValue: max-age=0
args: 
Request: /test.jpg
 Arguments: 

<Delay of around 2 seconds>

New client
method: GET url: /test.jpg search: 
headerName: Host
headerValue: 192.168.4.1
headerName: User-Agent
headerValue: Mozilla/5.0 (Windows NT 10.0; WOW64; rv:61.0) Gecko/20100101 Firefox/61.0
headerName: Accept
headerValue: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
headerName: Accept-Language
headerValue: de,en-US;q=0.7,en;q=0.3
headerName: Accept-Encoding
headerValue: gzip, deflate
headerName: Connection
headerValue: keep-alive
headerName: Upgrade-Insecure-Requests
headerValue: 1
headerName: Cache-Control
headerValue: max-age=0
args: 
Request: /test.jpg
 Arguments: 

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions