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

Memory leak ESP8266WebServer #230

Closed
robertgregor opened this issue May 12, 2015 · 7 comments
Closed

Memory leak ESP8266WebServer #230

robertgregor opened this issue May 12, 2015 · 7 comments

Comments

@robertgregor
Copy link

Hello, I have a sketch, which is using the webserver. Seems there is memory leak, thus using timer, I am printing each 2 seconds:
Serial.print("Free heap:");
Serial.println(ESP.getFreeHeap(),DEC);

I did the regular access to the Webserver port - and it was in debug mode and see the output:

Free heap:6288
Free heap:6288
Free heap:6288
Free heap:6288
New client
method: GET url: / search:
args:
Request: /
Arguments:
Free heap:6056
Free heap:6056
Free heap:6056
Free heap:6056
Free heap:6056
New client
method: GET url: /cwd search:
args:
Request: /cwd
Arguments:
Free heap:5864
Free heap:5864
Free heap:5864
Free heap:5864
New client
method: GET url: /cww search:
args:
Request: /cww
Arguments:
Free heap:5672
Free heap:5672
Free heap:5672
Free heap:5672
Free heap:5672
Free heap:5672
Free heap:5672
Free heap:5672
Free heap:5672
Free heap:5672
New client
method: GET url: / search:
args:
Request: /
Arguments:
Free heap:5480
Free heap:5480
New client
method: GET url: / search:
args:
Request: /
Arguments:
Free heap:5288
Free heap:5288
New client
method: GET url: / search:
args:
Request: /
Arguments:
Free heap:5096
New client
method: GET url: / search:
args:
Request: /
Arguments:
Free heap:4904
New client
method: GET url: / search:
args:
Request: /
Arguments:
Free heap:4712
Free heap:4712
New client
method: GET url: / search:
args:
Request: /
Arguments:
Free heap:4520
Free heap:4520
New client
method: GET url: / search:
args:
Request: /
Arguments:
Free heap:4328
Free heap:4528
New client
method: GET url: / search:
args:
Request: /
Arguments:
Free heap:4336
New client
method: GET url: / search:
args:
Request: /
Arguments:
Free heap:4144
Free heap:4144
New client
method: GET url: / search:
args:
Request: /
Arguments:
Free heap:3952
New client
method: GET url: / search:
args:
Request: /
Arguments:
Free heap:3952
New client
method: GET url: / search:
args:
Request: /
Arguments:
Free heap:3760
New client
method: GET url: / search:
args:
Request: /
Arguments:
Free heap:3568
New client
method: GET url: / search:
args:
Request: /
Arguments:
Free heap:3376
Free heap:3376
Free heap:3568

It seems, that with each request, there is lost of the 200 bytes...

@igrr
Copy link
Member

igrr commented May 12, 2015

Free heap:3376
Free heap:3376
Free heap:3568

As you see, memory gets reclaimed, so it is not lost.
Closed connections go into TIME_WAIT state where they must be kept by the TCP stack for 2xMSL interval. We might though add client.abort() method to just send RST segment and be done with the connection fast...

@robertgregor
Copy link
Author

OK, thanks, yes, I see now. I did several tests and yes, you are correct.

@Lukaspp
Copy link

Lukaspp commented Jun 27, 2015

Thanks for your job.

I would like to know if there is a solution for the leak memory when server has 1 or 2 connections per second over a period of time?

Every cycle the memory is going down until it is not enough. But if the cycle stop (no connections) for a while, memory is recovering again.

Thanks for your help and best regards,

@Lukaspp
Copy link

Lukaspp commented Jun 29, 2015

This could be a Solution:

ReinholdHiller wrote:
In clientcontext.h I changed line 70 and following (the following if ()... is now useless, but for a test.) to:

err = tcp_close(_pcb);
tcp_abort(_pcb);
if(err != ERR_OK) {

This fixes the "memory leak" and does not seem to harm the Webserver example.

But the file is a little different now, so: I could figure it out. Modification is made for the current file release at line 64.

ClientContext.h

64 err = tcp_close(_pcb);
65 tcp_abort(_pcb); // Modification 28-06-2015
66 if(err != ERR_OK) {
67 DEBUGV(":tc err %d\r\n", err);
68 tcp_abort(_pcb);
69 err = ERR_ABRT;

Very good Jop.

Best regards

@porcao
Copy link

porcao commented Aug 24, 2015

Lukaspp, I was the same mistake here. Exception ( 9). Practically unfeasible my project.
Your solution seems to have worked perfectly! I am at a few hours testing and not getting over the error.
Thank you for sharing!

pfabri added a commit to pfabri/Arduino that referenced this issue Dec 15, 2016
This branch adds a close_abort() method to the WiFiClient class.

How it works, what it does:
Calling `close_abort()` will close and abort the client connection it
is invoked on and, as a result, free its resources (i.e. memory).

**WARNING:** aborting connections without a good reason violates the
TCP protocol, because a closed connection would normally need to
spend some time in `TIME_WAIT` state before its resources are freed.

Usage example:
    WiFiClient client;		// set up a client

    { /* do things with your client */ }

    client.stop_abort()		// when you're done,abort the
				// connection if you must

Why it's useful:
1. Give programmers a way to shut down connections immediately if
   need be. The underlying `tcp.c` file has an abort function, but
   this has not been directly accessible via the `WiFiClient`
   class until now.

2. There are a number of reported issues for the repository
   addressing the heap corruption that can result from trying to
   retain too many connections in `TIME_WAIT` state (most notably:
   esp8266#230, esp8266#1070, esp8266#1923). Although the warning above holds, there may be
   circumstances where this isn't very important. For example an ESP8266
   running in AP mode hosting a page, which requests a new
   connection every second via an AJAX script to  monitor
   a sensor/button/etc. continusously.

Currently existing alternative approach:
When building a project, defining the
`-D MEMP_NUM_TCP_PCB_TIME_WAIT=5`compiler directive will limit the
maximum number of clients allowed to stay in TIME_WAIT state. `5` is
the default, lower it as necessary. See reference
[here](https://github.com/esp8266/Arduino/blob/master/tools/sdk/lwip/include/lwipopts.h#L263)

Thanks:
Thank you to @me-no-dev, @everslick and @Palatis for bringing the `
MEMP_NUM_TCP_PCB_TIME_WAIT` option to my attention.
@dun46
Copy link

dun46 commented Jan 24, 2017

Hi, thanks to this post I have been able to solve a similar problem
thank you very much

@laercionit
Copy link
Contributor

Hello, good night, I have this problem currently using CORE 2.6.3 with WEBServer and NTP.
Anyone going through this now?

vamas added a commit to vamas/Arduino that referenced this issue May 30, 2020
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

6 participants