From d0171574d857cfc8cb09a192ecbd541ebdbf08b3 Mon Sep 17 00:00:00 2001 From: "Earle F. Philhower, III" Date: Wed, 26 Sep 2018 08:47:10 -0700 Subject: [PATCH] Fix TCP race condition, remove fixed delay in CC (#5167) ClientContext::_wait_for_sent() could dereference a TCP's _pcb after the connection was dropped by the OS, resulting in a crash. Move the connection dropped check to catch this case, and replace a fixed millisecond delay() with a yield and timeout value to minimize wasted time when transmission completes. --- .../ESP8266WiFi/src/include/ClientContext.h | 33 ++++++++++--------- 1 file changed, 17 insertions(+), 16 deletions(-) diff --git a/libraries/ESP8266WiFi/src/include/ClientContext.h b/libraries/ESP8266WiFi/src/include/ClientContext.h index 86327dc40..e0841d1c5 100644 --- a/libraries/ESP8266WiFi/src/include/ClientContext.h +++ b/libraries/ESP8266WiFi/src/include/ClientContext.h @@ -308,13 +308,19 @@ public: if (!_pcb) return true; - int loop = -1; int prevsndbuf = -1; - max_wait_ms++; // wait for peer's acks to flush lwIP's output buffer - + uint32_t last_sent = millis(); while (1) { + if (millis() - last_sent > (uint32_t) max_wait_ms) { +#ifdef DEBUGV + // wait until sent: timeout + DEBUGV(":wustmo\n"); +#endif + // All data was not flushed, timeout hit + return false; + } // force lwIP to send what can be sent tcp_output(_pcb); @@ -322,25 +328,20 @@ public: int sndbuf = tcp_sndbuf(_pcb); if (sndbuf != prevsndbuf) { // send buffer has changed (or first iteration) - // we received an ack: restart the loop counter prevsndbuf = sndbuf; - loop = max_wait_ms; + // We just sent a bit, move timeout forward + last_sent = millis(); } - if (state() != ESTABLISHED || sndbuf == TCP_SND_BUF || --loop <= 0) + yield(); + + if ((state() != ESTABLISHED) || (sndbuf == TCP_SND_BUF)) { break; - - delay(1); + } } - #ifdef DEBUGV - if (loop <= 0) { - // wait until sent: timeout - DEBUGV(":wustmo\n"); - } - #endif - - return max_wait_ms > 0; + // All data flushed + return true; } uint8_t state() const