From f5a7cbed0c306f69cee7f6b54a728488fc9692d2 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Thu, 17 Sep 2026 16:48:52 -0500 Subject: [PATCH] Scope the fallback to null frames, count only successful retries, and rate limit the warning --- .../wifi/wifi_component_esp8266.cpp | 20 +++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/esphome/components/wifi/wifi_component_esp8266.cpp b/esphome/components/wifi/wifi_component_esp8266.cpp index fd3c9ee3558..eb424174fd0 100644 --- a/esphome/components/wifi/wifi_component_esp8266.cpp +++ b/esphome/components/wifi/wifi_component_esp8266.cpp @@ -43,6 +43,8 @@ extern "C" { static constexpr int SMALL_MGMT_FRAME_MAX = 64; // Times the small pool was empty and a heap buffer was handed out instead. static uint8_t s_small_mgmt_pool_exhausted_count = 0; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables) +static uint32_t s_small_mgmt_pool_last_log = 0; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables) +static constexpr uint32_t SMALL_MGMT_POOL_LOG_INTERVAL_MS = 10000; // NOLINTBEGIN(bugprone-reserved-identifier,cert-dcl37-c,cert-dcl51-cpp,readability-identifier-naming) extern "C" { @@ -51,13 +53,15 @@ void *__real_ieee80211_getmgtframe(void **frm, int headroom, int pktlen); // When the small pool is empty the SDK returns nullptr and pm_send_nullfunc spins in an // assert until the soft watchdog resets the device (#19371). Retry with a size just above // the pool limit so the SDK takes the heap backed path it already uses for larger frames. +// Only null frames (no body) get the retry; every other caller drops its frame on nullptr. void *__wrap_ieee80211_getmgtframe(void **frm, int headroom, int pktlen) { void *buf = __real_ieee80211_getmgtframe(frm, headroom, pktlen); - if (buf != nullptr || headroom + pktlen > SMALL_MGMT_FRAME_MAX) + if (buf != nullptr || pktlen != 0 || headroom > SMALL_MGMT_FRAME_MAX) return buf; - if (s_small_mgmt_pool_exhausted_count != UINT8_MAX) + buf = __real_ieee80211_getmgtframe(frm, headroom, SMALL_MGMT_FRAME_MAX + 1 - headroom); + if (buf != nullptr && s_small_mgmt_pool_exhausted_count != UINT8_MAX) s_small_mgmt_pool_exhausted_count++; - return __real_ieee80211_getmgtframe(frm, headroom, SMALL_MGMT_FRAME_MAX + 1 - headroom); + return buf; } } // NOLINTEND(bugprone-reserved-identifier,cert-dcl37-c,cert-dcl51-cpp,readability-identifier-naming) @@ -1006,9 +1010,13 @@ void WiFiComponent::process_pending_callbacks_() { // by notify_connect_state_listeners_() in the shared state machine code. if (s_small_mgmt_pool_exhausted_count != 0) { - ESP_LOGW(TAG, "SDK small management frame pool empty %u times, used heap instead", - s_small_mgmt_pool_exhausted_count); - s_small_mgmt_pool_exhausted_count = 0; + const uint32_t now = App.get_loop_component_start_time(); + if (now - s_small_mgmt_pool_last_log >= SMALL_MGMT_POOL_LOG_INTERVAL_MS) { + s_small_mgmt_pool_last_log = now; + ESP_LOGW(TAG, "SDK small management frame pool empty %u times, used heap instead", + s_small_mgmt_pool_exhausted_count); + s_small_mgmt_pool_exhausted_count = 0; + } } #ifdef USE_WIFI_CONNECT_STATE_LISTENERS