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 on WiFIClientSecure #6709

Closed
edodad opened this issue Nov 3, 2019 · 6 comments
Closed

Memory Leak on WiFIClientSecure #6709

edodad opened this issue Nov 3, 2019 · 6 comments

Comments

@edodad
Copy link

edodad commented Nov 3, 2019

Hi

ESP8266
Arduino Core 2.5.2
PubSubClient 2.7.0

Every time pubSubClient.connect() is called, WiFIClientSecure burns ~1KB of heap, every time, without releasing the OLD memoty

see also related issue
#4497

Every time ESP looses internet connection, pubSubClient.connect() is called and then it burns ~1KB of heap, every time, without releasing the OLD memoty

I tested it using Smartphone HotSpot, disabling the MOBILE DTATA (just MOBILE DATA) the re-enabling

Here below some code that reproduces the issue

#include <ESP8266WiFi.h>
#include <PubSubClient.h>

const char* ssid = "********";
const char* password = "***********";

const char* mqttServer = "***********";
const int mqttPort = 27468;
const char* mqttUser = "********";
const char* mqttPassword = "***********";

const char* ClientID = "ESP8266TEST";

WiFiClientSecure espClient;
PubSubClient client(espClient);

String GetStatus()
{
	return
		"ESP.getFreeContStack is " + String(ESP.getFreeContStack()) +
		", ESP.getFreeHeap is " + String(ESP.getFreeHeap()) +
		", WiFi.SSID is " + String(WiFi.SSID());
}

void setup_wifi() {

	delay(10);

	Serial.println();
	Serial.print("Connecting to ");
	Serial.println(ssid);

	WiFi.begin(ssid, password);

	while (WiFi.status() != WL_CONNECTED) {
		delay(500);
		Serial.print(".");
	}

	Serial.println("");
	Serial.println("WiFi connected");
	Serial.println("IP address: ");
	Serial.println(WiFi.localIP());
}

void reconnect() {


	Serial.println("reconnect()");

	while (!client.connected()) {
		Serial.print("Attempting MQTT connection...");
		Serial.println(GetStatus() + "...   ");
		// Attempt to connect
		if (client.connect(ClientID, mqttUser, mqttPassword)) {
			Serial.println("connected");
		}
		else {
			Serial.print("failed, rc=");
			Serial.print(client.state());
			Serial.println(" try again in 1 seconds");
			delay(1000);
		}
	}
}


void setup() {
	pinMode(BUILTIN_LED, OUTPUT);     // Initialize the BUILTIN_LED pin as an output
	Serial.begin(115200);
	setup_wifi();

	espClient.setInsecure();
	client.setServer(mqttServer, mqttPort);
}

int loopcount = 0;

void loop() {

	if (!client.connected()) {
		reconnect();
	}

	client.loop();

	if (++loopcount % 10000 == 0)
		Serial.println(GetStatus() + "...   ");
}
@Jeroen88
Copy link
Contributor

Jeroen88 commented Nov 4, 2019

If I recall correctly, your espClient should be completely destroyed to avoid this issue. Try:
WiFiClientSecure *espClient;

In setup():

espClient = new WiFiClientSecure; if(espClient != NULL) ...

And in reconnect()
delete espClient; espClient = new WiFiClientSecure; if(espClient != NULL) ...

Ofcourse reference espClient with '->' everywhere.

This might help!

@edodad
Copy link
Author

edodad commented Nov 4, 2019

Hi Jeroen

tried it but it doesnt work

pls see the code below... if you try it, you will see that every time you disable MOBILE DATA and the you enable DATA again, it burns 1KB of heap

Any other idea?

#include <ESP8266WiFi.h>
#include <PubSubClient.h>

#define USESSL

const char* ssid = "";
const char
password = "
";

const char* mqttServer = "";
const char
mqttUser = "
";
const char
mqttPassword = "
*********";

#ifdef USESSL
const int mqttPort = 27468;
WiFiClientSecure *espClient;
#else
const int mqttPort = 17468;
WiFiClient *espClient;
#endif // USESSL

const char* ClientID = "ESP8266TEST";

PubSubClient client;

String GetStatus()
{
return
"ESP.getFreeContStack is " + String(ESP.getFreeContStack()) +
", ESP.getFreeHeap is " + String(ESP.getFreeHeap()) +
", WiFi.SSID is " + String(WiFi.SSID());
}

void setup_wifi() {

delay(10);

Serial.println();
Serial.print("Connecting to ");
Serial.println(ssid);

WiFi.begin(ssid, password);

while (WiFi.status() != WL_CONNECTED) {
	delay(500);
	Serial.print(".");
}

Serial.println("");
Serial.println("WiFi connected");
Serial.println("IP address: ");
Serial.println(WiFi.localIP());

}

void reconnect() {

if (espClient != NULL) {
	delete espClient;
}

#ifdef USESSL
espClient = new WiFiClientSecure;
espClient->setInsecure();
#else
espClient = new WiFiClient;
#endif

client.setClient(*espClient);

Serial.println("reconnect()");

while (!client.connected()) {
	Serial.print("Attempting MQTT connection...");
	Serial.println(GetStatus() + "...   ");
	// Attempt to connect
	if (client.connect(ClientID, mqttUser, mqttPassword)) {
		Serial.println("connected");
	}
	else {
		Serial.print("failed, rc=");
		Serial.print(client.state());
		Serial.println(" try again in 1 seconds");
		delay(1000);
	}
}

}

void setup() {
pinMode(BUILTIN_LED, OUTPUT); // Initialize the BUILTIN_LED pin as an output
Serial.begin(115200);
setup_wifi();

client.setServer(mqttServer, mqttPort);

}

int loopcount = 0;

void loop() {

if (!client.connected()) {
	reconnect();
}

client.loop();

if (++loopcount % 10000 == 0)
	Serial.println(GetStatus() + "...   ");

}

@Jeroen88
Copy link
Contributor

Jeroen88 commented Nov 4, 2019

Try to mimic this example. This creates the WiFiClientSecure when it is needed. It does call connect() repeatedly but instead tests for begin() to return true.

The while (!client.connected()) loop still might cause the problem. I have no further ideas :/

@devyte
Copy link
Collaborator

devyte commented Nov 4, 2019

The handling of the WiFiClient is done within the pubsubclient code. We can't review or reverse engineer pubsubclient to figure out if they're doing something wrong, or if there really is an issue in our core. We just don't have the manpower, which is why we don't accept issues from 3rd party libs.
I suggest presenting the issue to the lib author and working with him, or investigating the lib internals yourself, to reduce to minimal code that only depends on our core where the problem is still present (MCVE, per issue template instructions which you ignored when opening this). If you get to that point, please open a new issue, follow the template instructions, and add the MCVE (reduced code) that shows the problem. We can look into it then.
Closing.

@devyte devyte closed this as completed Nov 4, 2019
@fsommer1968
Copy link

Edodad:
I haven't observed your error in my mqtt implementation, however the only difference I see so far that I call mqttclient.disconnect(); before mqttclient.connect(cfg.mqclid, cfg.mquname, cfg.mqpwd,0,0,0,0,false);

@Jeroen88
Copy link
Contributor

Jeroen88 commented Nov 4, 2019

@fsommer1968 suggestion might well work if disconnect() cleans up the client!

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