From fe6ba153bc3844c371f18f50206a568850abefb8 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Wed, 11 Mar 2026 21:32:11 -1000 Subject: [PATCH] [socket] Fix RP2040 socket_delay race that could miss a wake Remove the redundant s_socket_woke = false between the early-return check and the while loop. If an IRQ fires in that window (recv_fn sets s_socket_woke = true), clearing the flag would lose the wake and sleep until the timer fires. Now the while loop sees the flag immediately and exits. The flag is cleared after the loop instead. --- esphome/components/socket/lwip_raw_tcp_impl.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/esphome/components/socket/lwip_raw_tcp_impl.cpp b/esphome/components/socket/lwip_raw_tcp_impl.cpp index f6c7cc79010..d6f54ad3282 100644 --- a/esphome/components/socket/lwip_raw_tcp_impl.cpp +++ b/esphome/components/socket/lwip_raw_tcp_impl.cpp @@ -82,7 +82,9 @@ void socket_delay(uint32_t ms) { s_socket_woke = false; return; } - s_socket_woke = false; + // Don't clear s_socket_woke here — if an IRQ fires between the check above + // and the while loop below, the while condition sees it immediately. Clearing + // here would lose that wake and sleep until the timer fires. s_delay_expired = false; // Set a one-shot timer to wake us after the timeout. // add_alarm_in_ms returns >0 on success, 0 if time already passed, <0 on error. @@ -100,6 +102,7 @@ void socket_delay(uint32_t ms) { // Cancel timer if we woke early (socket data arrived before timeout) if (!s_delay_expired) cancel_alarm(alarm); + s_socket_woke = false; // consume the wake for next call } // No IRAM_ATTR equivalent needed: on RP2040, CYW43 async_context runs LWIP