From 31b8ba133cb3b0be55e71aa359e3bba3f9bfb51c Mon Sep 17 00:00:00 2001 From: David Gauchard Date: Thu, 22 Mar 2018 14:32:56 +0100 Subject: [PATCH 1/6] device test for #4516 (WiFiClient leaking) --- .../test_ClientContext/test_ClientContext.ino | 91 +++++++++++++++++++ 1 file changed, 91 insertions(+) create mode 100644 tests/device/test_ClientContext/test_ClientContext.ino diff --git a/tests/device/test_ClientContext/test_ClientContext.ino b/tests/device/test_ClientContext/test_ClientContext.ino new file mode 100644 index 0000000000..977835cc7f --- /dev/null +++ b/tests/device/test_ClientContext/test_ClientContext.ino @@ -0,0 +1,91 @@ +#include +#include +#include +#include +#include + +extern "C" { +#include "user_interface.h" +} + +BS_ENV_DECLARE(); + +// no need for #include +struct tcp_pcb; +extern struct tcp_pcb* tcp_tw_pcbs; +extern "C" void tcp_abort (struct tcp_pcb* pcb); + +void tcpCleanup (void) { + while (tcp_tw_pcbs) + tcp_abort(tcp_tw_pcbs); +} + +void setup() +{ + Serial.begin(115200); + Serial.setDebugOutput(true); + WiFi.persistent(false); + WiFi.mode(WIFI_STA); + WiFi.begin(STA_SSID, STA_PASS); + while (WiFi.status() != WL_CONNECTED) { + delay(500); + } + BS_RUN(Serial); +} + +TEST_CASE("WiFi release ClientContext", "[clientcontext]") +{ + #define LOOPS 20 + + // will search for a tcp server these gateway's ports + int ports [] = { 21, 23, 80, 443, 22, + 0 }; + WiFiClient client; + + Serial.print(WiFi.gatewayIP()); + + // look for reachable port on gateway + int port; + for (int i = 0; (port = ports[i]); i++) + if (client.connect(WiFi.gatewayIP(), ports[i])) { + client.stop(); + break; + } + + Serial.printf(":%d\r\n", port); + + int loops = 0; + int heapLost = 123456; + + if (port) { + + tcpCleanup(); + int heapStart = ESP.getFreeHeap(); + int minHeap = heapStart / 2; + int heap = heapStart; + Serial.printf("heap: %d\r\n", heap); + + while (++loops < LOOPS && (int)ESP.getFreeHeap() > minHeap) + if (client.connect(WiFi.gatewayIP(), port)) { + client.stop(); + tcpCleanup(); + int newHeap = (int)ESP.getFreeHeap(); + Serial.printf("%03d %5d %d\r\n", loops, newHeap, newHeap - heap); + heap = newHeap; + } + + heapLost = heapStart - ESP.getFreeHeap(); + + Serial.printf("min heap: %d\r\nheap: %d\r\nloops: %d\r\nheapLost: %d\r\n", + minHeap, + ESP.getFreeHeap(), + loops, + (int)heapLost); + } + + REQUIRE(loops == LOOPS && heapLost <= 0); +} + +void loop() +{ +} From 6eba68deb2cd114356696b1204f7ddb968e06646 Mon Sep 17 00:00:00 2001 From: David Gauchard Date: Thu, 22 Mar 2018 15:10:34 +0100 Subject: [PATCH 2/6] simply count the number of connections that do not change heap --- .../test_ClientContext/test_ClientContext.ino | 44 +++++++++++-------- 1 file changed, 25 insertions(+), 19 deletions(-) diff --git a/tests/device/test_ClientContext/test_ClientContext.ino b/tests/device/test_ClientContext/test_ClientContext.ino index 977835cc7f..78f0ccaafd 100644 --- a/tests/device/test_ClientContext/test_ClientContext.ino +++ b/tests/device/test_ClientContext/test_ClientContext.ino @@ -15,7 +15,8 @@ struct tcp_pcb; extern struct tcp_pcb* tcp_tw_pcbs; extern "C" void tcp_abort (struct tcp_pcb* pcb); -void tcpCleanup (void) { +void tcpCleanup (void) +{ while (tcp_tw_pcbs) tcp_abort(tcp_tw_pcbs); } @@ -35,7 +36,8 @@ void setup() TEST_CASE("WiFi release ClientContext", "[clientcontext]") { - #define LOOPS 20 + #define MAXLOOPS 50 + #define SUCCESS_GOAL 10 // will search for a tcp server these gateway's ports int ports [] = { 21, 23, 80, 443, 22, @@ -47,43 +49,47 @@ TEST_CASE("WiFi release ClientContext", "[clientcontext]") // look for reachable port on gateway int port; for (int i = 0; (port = ports[i]); i++) - if (client.connect(WiFi.gatewayIP(), ports[i])) { - client.stop(); - break; - } + if (client.connect(WiFi.gatewayIP(), ports[i])) + { + client.stop(); + break; + } Serial.printf(":%d\r\n", port); int loops = 0; int heapLost = 123456; + int success = 0; - if (port) { - + if (port) + { tcpCleanup(); int heapStart = ESP.getFreeHeap(); int minHeap = heapStart / 2; int heap = heapStart; - Serial.printf("heap: %d\r\n", heap); + Serial.printf("heap: %d\r\n", heap); - while (++loops < LOOPS && (int)ESP.getFreeHeap() > minHeap) - if (client.connect(WiFi.gatewayIP(), port)) { + while (success < SUCCESS_GOAL && ++loops <= MAXLOOPS && (int)ESP.getFreeHeap() > minHeap) + if (client.connect(WiFi.gatewayIP(), port)) + { client.stop(); tcpCleanup(); int newHeap = (int)ESP.getFreeHeap(); - Serial.printf("%03d %5d %d\r\n", loops, newHeap, newHeap - heap); - heap = newHeap; + Serial.printf("%03d %5d %d\r\n", loops, newHeap, newHeap - heap); + if (newHeap - heap == 0) + success++; + heap = newHeap; } - heapLost = heapStart - ESP.getFreeHeap(); - - Serial.printf("min heap: %d\r\nheap: %d\r\nloops: %d\r\nheapLost: %d\r\n", - minHeap, + Serial.printf("heap: %d\r\nheapLost: %d\r\n" + "loops: %d\r\nstable-loops: %d\r\n", ESP.getFreeHeap(), + heapLost, loops, - (int)heapLost); + success); } - REQUIRE(loops == LOOPS && heapLost <= 0); + REQUIRE(success >= SUCCESS_GOAL); } void loop() From 2f02b13afda59c262101d0de198c642e697017f6 Mon Sep 17 00:00:00 2001 From: David Gauchard Date: Thu, 22 Mar 2018 15:23:57 +0100 Subject: [PATCH 3/6] remove unused heapLost --- tests/device/test_ClientContext/test_ClientContext.ino | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/tests/device/test_ClientContext/test_ClientContext.ino b/tests/device/test_ClientContext/test_ClientContext.ino index 78f0ccaafd..b110bcf675 100644 --- a/tests/device/test_ClientContext/test_ClientContext.ino +++ b/tests/device/test_ClientContext/test_ClientContext.ino @@ -58,7 +58,6 @@ TEST_CASE("WiFi release ClientContext", "[clientcontext]") Serial.printf(":%d\r\n", port); int loops = 0; - int heapLost = 123456; int success = 0; if (port) @@ -81,10 +80,9 @@ TEST_CASE("WiFi release ClientContext", "[clientcontext]") heap = newHeap; } - Serial.printf("heap: %d\r\nheapLost: %d\r\n" + Serial.printf("heap: %d\r\n" "loops: %d\r\nstable-loops: %d\r\n", ESP.getFreeHeap(), - heapLost, loops, success); } From 24ed65cebea872935d0d99f9ac98feab29fb6082 Mon Sep 17 00:00:00 2001 From: David Gauchard Date: Thu, 22 Mar 2018 18:46:34 +0100 Subject: [PATCH 4/6] + python server (to not depend on gateway's opened tcp port) --- .../test_ClientContext/test_ClientContext.ino | 16 ++--- .../test_ClientContext/test_ClientContext.py | 60 +++++++++++++++++++ 2 files changed, 68 insertions(+), 8 deletions(-) create mode 100644 tests/device/test_ClientContext/test_ClientContext.py diff --git a/tests/device/test_ClientContext/test_ClientContext.ino b/tests/device/test_ClientContext/test_ClientContext.ino index b110bcf675..918a45eed3 100644 --- a/tests/device/test_ClientContext/test_ClientContext.ino +++ b/tests/device/test_ClientContext/test_ClientContext.ino @@ -2,7 +2,6 @@ #include #include #include -#include extern "C" { #include "user_interface.h" @@ -36,24 +35,25 @@ void setup() TEST_CASE("WiFi release ClientContext", "[clientcontext]") { - #define MAXLOOPS 50 + #define MAXLOOPS 50 #define SUCCESS_GOAL 10 + #define srv SERVER_IP + #define srv WiFi.gatewayIP() - // will search for a tcp server these gateway's ports - int ports [] = { 21, 23, 80, 443, 22, - 0 }; WiFiClient client; - Serial.print(WiFi.gatewayIP()); + Serial.print(srv); // look for reachable port on gateway int port; - for (int i = 0; (port = ports[i]); i++) - if (client.connect(WiFi.gatewayIP(), ports[i])) + for (port = 8266; port <= 8285; port++) + if (client.connect(srv, port)) { client.stop(); break; } + if (port > 8285) + port = 0; Serial.printf(":%d\r\n", port); diff --git a/tests/device/test_ClientContext/test_ClientContext.py b/tests/device/test_ClientContext/test_ClientContext.py new file mode 100644 index 0000000000..ae29bcd2fe --- /dev/null +++ b/tests/device/test_ClientContext/test_ClientContext.py @@ -0,0 +1,60 @@ +from mock_decorators import setup, teardown +from flask import Flask, request +from threading import Thread +import socket +import select +import sys +import os + +@setup('WiFi release ClientContext') +def setup_tcpsrv(e): + + global thread + + app = Flask(__name__) + + def run(): + + global running + + running = False + sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + for port in range(8266, 8285 + 1): + try: + print >>sys.stderr, 'trying port', port + server_address = ("0.0.0.0", port) + sock.bind(server_address) + sock.listen(1) + running = True + break + except Exception: + print >>sys.stderr, 'busy' + if not running: + return + print >>sys.stderr, 'starting up on %s port %s' % server_address + print >>sys.stderr, 'waiting for connections' + while running: + print >>sys.stderr, 'loop' + readable, writable, errored = select.select([sock], [], [], 1.0) + if readable: + connection, client_address = sock.accept() + try: + print >>sys.stderr, 'client connected:', client_address + finally: + print >>sys.stderr, 'close' + connection.shutdown(socket.SHUT_RDWR) + connection.close() + + thread = Thread(target=run) + thread.start() + +@teardown('WiFi release ClientContext') +def teardown_tcpsrv(e): + + global thread + global running + + print >>sys.stderr, 'closing' + running = False + thread.join() + return 0 From 46839d25d822e6a8a7888e2f0629ca04125fccc0 Mon Sep 17 00:00:00 2001 From: David Gauchard Date: Thu, 22 Mar 2018 18:57:32 +0100 Subject: [PATCH 5/6] remove old&bad define --- tests/device/test_ClientContext/test_ClientContext.ino | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/device/test_ClientContext/test_ClientContext.ino b/tests/device/test_ClientContext/test_ClientContext.ino index 918a45eed3..1f202e2ec8 100644 --- a/tests/device/test_ClientContext/test_ClientContext.ino +++ b/tests/device/test_ClientContext/test_ClientContext.ino @@ -38,7 +38,6 @@ TEST_CASE("WiFi release ClientContext", "[clientcontext]") #define MAXLOOPS 50 #define SUCCESS_GOAL 10 #define srv SERVER_IP - #define srv WiFi.gatewayIP() WiFiClient client; From df5b26c83f80c1ff57258cce315e9026d55506f0 Mon Sep 17 00:00:00 2001 From: David Gauchard Date: Thu, 22 Mar 2018 19:06:16 +0100 Subject: [PATCH 6/6] fix another old address --- tests/device/test_ClientContext/test_ClientContext.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/device/test_ClientContext/test_ClientContext.ino b/tests/device/test_ClientContext/test_ClientContext.ino index 1f202e2ec8..ea6ea015dc 100644 --- a/tests/device/test_ClientContext/test_ClientContext.ino +++ b/tests/device/test_ClientContext/test_ClientContext.ino @@ -68,7 +68,7 @@ TEST_CASE("WiFi release ClientContext", "[clientcontext]") Serial.printf("heap: %d\r\n", heap); while (success < SUCCESS_GOAL && ++loops <= MAXLOOPS && (int)ESP.getFreeHeap() > minHeap) - if (client.connect(WiFi.gatewayIP(), port)) + if (client.connect(srv, port)) { client.stop(); tcpCleanup();