From 547e25e699388fa61f92f644ba53ae399d5d858f Mon Sep 17 00:00:00 2001 From: Mathieu Carbou Date: Tue, 20 Jan 2026 10:34:37 +0100 Subject: [PATCH 1/3] Code cleanup and null checks --- src/AsyncEventSource.cpp | 41 +++++++++++++++++++++++++--------------- 1 file changed, 26 insertions(+), 15 deletions(-) diff --git a/src/AsyncEventSource.cpp b/src/AsyncEventSource.cpp index 7b95b48a..e6779050 100644 --- a/src/AsyncEventSource.cpp +++ b/src/AsyncEventSource.cpp @@ -217,8 +217,12 @@ bool AsyncEventSourceClient::_queueMessage(const char *message, size_t len) { forcing Q run will only eat more heap ram and blow the buffer, let's just keep data in our own queue the queue will be processed at least on each onAck()/onPoll() call from AsyncTCP */ - if (_messageQueue.size() < SSE_MAX_QUEUED_MESSAGES >> 2 && _client->canSend()) { + if (_client && _client->canSend() && _messageQueue.size() < SSE_MAX_QUEUED_MESSAGES >> 2) { _runQueue(); + + } else if (!_client) { + _messageQueue.clear(); + return false; } return true; @@ -243,9 +247,14 @@ bool AsyncEventSourceClient::_queueMessage(AsyncEvent_SharedData_t &&msg) { forcing Q run will only eat more heap ram and blow the buffer, let's just keep data in our own queue the queue will be processed at least on each onAck()/onPoll() call from AsyncTCP */ - if (_messageQueue.size() < SSE_MAX_QUEUED_MESSAGES >> 2 && _client->canSend()) { + if (_client && _client->canSend() && _messageQueue.size() < SSE_MAX_QUEUED_MESSAGES >> 2) { _runQueue(); + + } else if (!_client) { + _messageQueue.clear(); + return false; } + return true; } @@ -334,7 +343,7 @@ void AsyncEventSourceClient::_runQueue() { } // flush socket - if (total_bytes_written) { + if (total_bytes_written && _client) { _client->send(); } } @@ -410,17 +419,13 @@ size_t AsyncEventSource::avgPacketsWaiting() const { #ifdef ESP32 std::lock_guard lock(_client_queue_lock); #endif - if (!_clients.size()) { - return 0; - } - for (const auto &c : _clients) { if (c->connected()) { aql += c->packetsWaiting(); ++nConnectedClients; } } - return ((aql) + (nConnectedClients / 2)) / (nConnectedClients); // round up + return nConnectedClients == 0 ? 0 : ((aql) + (nConnectedClients / 2)) / (nConnectedClients); // round up } AsyncEventSource::SendStatus AsyncEventSource::send(const char *message, const char *event, uint32_t id, uint32_t reconnect) { @@ -431,10 +436,12 @@ AsyncEventSource::SendStatus AsyncEventSource::send(const char *message, const c size_t hits = 0; size_t miss = 0; for (const auto &c : _clients) { - if (c->write(shared_msg)) { - ++hits; - } else { - ++miss; + if (c->connected()) { + if (c->write(shared_msg)) { + ++hits; + } else { + ++miss; + } } } return hits == 0 ? DISCARDED : (miss == 0 ? ENQUEUED : PARTIALLY_ENQUEUED); @@ -462,11 +469,15 @@ void AsyncEventSource::handleRequest(AsyncWebServerRequest *request) { request->send(new AsyncEventSourceResponse(this)); } +// list iteration protected by caller's lock void AsyncEventSource::_adjust_inflight_window() { - if (_clients.size()) { - size_t inflight = SSE_MAX_INFLIGH / _clients.size(); + const size_t clientCount = count(); + if (clientCount) { + size_t inflight = SSE_MAX_INFLIGH / clientCount; for (const auto &c : _clients) { - c->set_max_inflight_bytes(inflight); + if (c->connected()) { + c->set_max_inflight_bytes(inflight); + } } // Serial.printf("adjusted inflight to: %u\n", inflight); } From 13d6ccfd4ba83a4eabdcd6c2d03e372b39dbd0aa Mon Sep 17 00:00:00 2001 From: Mathieu Carbou Date: Thu, 22 Jan 2026 15:14:00 +0100 Subject: [PATCH 2/3] copilot review --- src/AsyncEventSource.cpp | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/src/AsyncEventSource.cpp b/src/AsyncEventSource.cpp index e6779050..d0f34730 100644 --- a/src/AsyncEventSource.cpp +++ b/src/AsyncEventSource.cpp @@ -209,7 +209,12 @@ bool AsyncEventSourceClient::_queueMessage(const char *message, size_t len) { std::lock_guard lock(_lockmq); #endif - _messageQueue.emplace_back(message, len); + if (_client) { + _messageQueue.emplace_back(message, len); + } else { + _messageQueue.clear(); + return false; + } /* throttle queue run @@ -219,10 +224,6 @@ bool AsyncEventSourceClient::_queueMessage(const char *message, size_t len) { */ if (_client && _client->canSend() && _messageQueue.size() < SSE_MAX_QUEUED_MESSAGES >> 2) { _runQueue(); - - } else if (!_client) { - _messageQueue.clear(); - return false; } return true; @@ -239,7 +240,12 @@ bool AsyncEventSourceClient::_queueMessage(AsyncEvent_SharedData_t &&msg) { std::lock_guard lock(_lockmq); #endif - _messageQueue.emplace_back(std::move(msg)); + if (_client) { + _messageQueue.emplace_back(std::move(msg)); + } else { + _messageQueue.clear(); + return false; + } /* throttle queue run @@ -249,12 +255,7 @@ bool AsyncEventSourceClient::_queueMessage(AsyncEvent_SharedData_t &&msg) { */ if (_client && _client->canSend() && _messageQueue.size() < SSE_MAX_QUEUED_MESSAGES >> 2) { _runQueue(); - - } else if (!_client) { - _messageQueue.clear(); - return false; } - return true; } @@ -343,7 +344,7 @@ void AsyncEventSourceClient::_runQueue() { } // flush socket - if (total_bytes_written && _client) { + if (_client && total_bytes_written) { _client->send(); } } From de7cb0dcb3cecd23fd9b6f96470faa90736b8276 Mon Sep 17 00:00:00 2001 From: Mathieu Carbou Date: Thu, 22 Jan 2026 16:02:23 +0100 Subject: [PATCH 3/3] cleanup comment --- src/AsyncWebServerLogging.h | 1 - 1 file changed, 1 deletion(-) diff --git a/src/AsyncWebServerLogging.h b/src/AsyncWebServerLogging.h index e498f5d8..21b75824 100644 --- a/src/AsyncWebServerLogging.h +++ b/src/AsyncWebServerLogging.h @@ -81,7 +81,6 @@ /** * ESP8266 specific configurations - * Note: __FUNCTION__ is stored in flash on ESP8266, so we use FPSTR() to handle it properly */ #elif defined(ESP8266) #include