-
Notifications
You must be signed in to change notification settings - Fork 13.3k
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
API in WiFiClient to save heap memory #8732
Conversation
When used by a server heap memory decrease drastically after numero client acces. Sockets in TIME_WAIT stay after the server issues a Client.stop which causes a server crash (and reboot) after some hours or some minutes. Note that the proposed method tcpCleanup in #1923 does not work because the instruction "extern struct tcp_pcb* tcp_tw_pcbs;" does NOT initialise tcp_tw_pcbs to the one used by the Client. It is only a declaration and because it is only a declaration, tcp_tw_pcbs is set to NULL. Consecuently tcp_abort(tcp_tw_pcbs) is never called.
Reading doc and actual impl, tcp_abort -> tcp_abandon will free pcb from under you. After that, pcb ptr is technically freed and returned to the shared memory poll. Anything doing anything on Seems kind of dangerous to include as public api, unless we handle things ourselves in the proper order. Another thing is tcp_... API should preferably go to ClientContext, which actually holds the pcb |
1- I did not found any doc on tcp_abandon. Could you please give me a link to that doc ? 2- Yes, tcp_pcb* is held by ClientContext and thats the reason why I called _client->getPCB() which has to be called from inside Client object and passed to tcp_abort(tcp_pcb*) after initialization with _client->getPCB(). |
Ok thanks for the links. But reading the links you sent to me, I found that it is possible to kill the oldest connection in TIME_WAIT by mean of calling tcp_kill_timewait(void). No pointer to pass to this function, so easy to use. I will try it making some calls to this function from time to time when the server is running and see what happens. Just an additional remark: It is said in the doc that tcp_kill_timewait is called from tcp_alloc() if no more connections are available. So when a server is running accepting a lot of connections from clients and stopping them one after the other, tcp_alloc should call tcp_kill_timewait from time to time not to face with a malloc failure. |
Hello, as mentionned in my previous response I made an experiment using tcp_kill_timewait(). Inside the server I made a call after every Client.close but after some minutes of frequent clients connections (4 connections randomly every 30 seconds) the server crashes (not enough heap memory available). Obviously it was not enough to kill sockets in TIME_WAIT state. So the only way I found avoid insufficient heap memory available is to systematically abort client's pcb. For this I did not found any other solution than; WiFiClient.h: bool stopAndAbortPcb(); // new API WiFiClient.cpp; // Api for heap saving. Optional use instead of WiFiClient::stop to systematically retreive some heap memory when closing a client Using this optional API the server works hours and hours without crashing. No lack of heap memory even with very frequent clients accesses to the server. What would be your opinion on adding such an API in WiFiClient class ? Would you accept such a pull request if I'd propose it ? |
Ok, lets add that. But
|
When used by a server, heap memory decrease drastically after numerous client acces (Client=Server.available()) because sockets in TIME_WAIT remains too much time after issuing Client.stop by the server in comparison with the ESP8266 memory capacity.
These TIME_WAIT sockets causes a server crash (and random reboot) after some hours or sometimes some minutes running due to lack of available heap memory.
Note that the proposed method tcpCleanup in #1923 does not work because the instruction "extern struct tcp_pcb* tcp_tw_pcbs;" does NOT initialise tcp_tw_pcbs to the one used by the Client. It is only a declaration and because it is only a declaration, tcp_tw_pcbs is set to NULL. Consecuently tcp_abort(tcp_tw_pcbs) is never called.
The proposed request creates an API for an effective call to tcp_abort.
It has to be called before issuing an Client.stop().
With this method heap memory's server does not decrease even in case of frequent clients access an will run hours and days without crashing.
Using this API is of course optional.