[mdns] Skip MDNS.update() while the ESP8266 radio cannot transmit (#18785)

This commit is contained in:
J. Nick Koston
2026-08-31 11:25:10 +12:00
committed by Jesse Hills
parent 8929fc43d8
commit 20d4fe1a41
5 changed files with 25 additions and 6 deletions
+13 -1
View File
@@ -41,7 +41,19 @@ static void register_esp8266(MDNSComponent *, StaticVector<MDNSService, MDNS_SER
#ifdef USE_MDNS_EVENT_DRIVEN_POLLING
void MDNSComponent::start_polling_window_() {
// uint32_t-ID set_interval/set_timeout already does atomic cancel-and-add.
this->set_interval(MDNS_POLL_ID, MDNS_UPDATE_INTERVAL_MS, []() { MDNS.update(); });
this->set_interval(MDNS_POLL_ID, MDNS_UPDATE_INTERVAL_MS, []() {
#ifdef USE_MDNS_WIFI_LISTENER
// MDNS.update() can suspend the loop in UdpContext::sendTimeout() while a send is
// failing (radio off-channel during a roam scan, or mid reconnect); an incoming
// packet then re-enters LEAmDNS from lwIP and corrupts shared UdpContext state.
// Skip the tick while the radio cannot transmit (#18760), but keep polling while
// the AP is serving clients (AP-only or fallback AP with the STA down).
auto *wifi = wifi::global_wifi_component;
if (wifi->is_roaming() || (!wifi->is_connected() && !wifi->is_ap_active()))
return;
#endif
MDNS.update();
});
this->set_timeout(MDNS_POLL_STOP_ID, MDNS_POLL_WINDOW_MS, [this]() { this->cancel_interval(MDNS_POLL_ID); });
}
#endif
+3 -3
View File
@@ -530,7 +530,7 @@ void WiFiComponent::log_discarded_scan_result_(const char *ssid, const uint8_t *
#if ESPHOME_LOG_LEVEL >= ESPHOME_LOG_LEVEL_VERBOSE
// Skip logging during roaming scans to avoid log buffer overflow
// (roaming scans typically find many networks but only care about same-SSID APs)
if (this->roaming_state_ == RoamingState::SCANNING) {
if (this->is_roaming_scan_active()) {
return;
}
char bssid_s[MAC_ADDRESS_PRETTY_BUFFER_SIZE];
@@ -835,7 +835,7 @@ void WiFiComponent::loop() {
// Post-connect roaming: check for better AP
if (this->post_connect_roaming_) {
if (this->roaming_state_ == RoamingState::SCANNING) {
if (this->is_roaming_scan_active()) {
if (this->scan_done_) {
this->process_roaming_scan_();
}
@@ -2152,7 +2152,7 @@ void WiFiComponent::retry_connect() {
// Roam connection failed - transition to reconnecting
ESP_LOGD(TAG, "Roam failed, reconnecting (attempt %u/%u)", this->roaming_attempts_, ROAMING_MAX_ATTEMPTS);
this->roaming_state_ = RoamingState::RECONNECTING;
} else if (this->roaming_state_ == RoamingState::SCANNING) {
} else if (this->is_roaming_scan_active()) {
// Disconnected during roam scan - transition to RECONNECTING so the attempts
// counter is preserved when reconnection succeeds (IDLE would reset it)
ESP_LOGD(TAG, "Disconnected during roam scan (attempt %u/%u)", this->roaming_attempts_, ROAMING_MAX_ATTEMPTS);
+7
View File
@@ -475,6 +475,13 @@ class WiFiComponent final : public Component {
bool is_connected() const { return this->connected_; }
/// True while a post-connect roaming scan holds the radio off-channel.
bool is_roaming_scan_active() const { return this->roaming_state_ == RoamingState::SCANNING; }
/// True while a post-connect roam is in progress (scanning off-channel, reassociating,
/// or recovering from a failed roam).
bool is_roaming() const { return this->roaming_state_ != RoamingState::IDLE; }
#ifdef USE_ESP32
/// esp_netif handle of the station interface, used by network for default-route
/// arbitration. nullptr until wifi_lazy_init_() has run.
@@ -717,7 +717,7 @@ bool WiFiComponent::wifi_scan_start_(bool passive) {
static constexpr uint32_t SCAN_ACTIVE_MAX_DEFAULT_MS = 500;
static constexpr uint32_t SCAN_ACTIVE_MIN_ROAMING_MS = 100;
static constexpr uint32_t SCAN_ACTIVE_MAX_ROAMING_MS = 300;
bool roaming = this->roaming_state_ == RoamingState::SCANNING;
bool roaming = this->is_roaming_scan_active();
if (passive) {
config.scan_time.passive = roaming ? SCAN_PASSIVE_ROAMING_MS : SCAN_PASSIVE_DEFAULT_MS;
} else {
@@ -1064,7 +1064,7 @@ bool WiFiComponent::wifi_scan_start_(bool passive) {
// When scanning while connected (roaming), return to home channel between
// each scanned channel to maintain the connection (helps with BLE/WiFi coexistence)
#ifdef CONFIG_SOC_WIFI_SUPPORTED
if (this->roaming_state_ == RoamingState::SCANNING) {
if (this->is_roaming_scan_active()) {
config.coex_background_scan = true;
}
#endif