From 59a8057e9ad95f70d433f8a407eb540b86332797 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Thu, 30 Apr 2026 06:33:49 -0500 Subject: [PATCH] [core] Inline loop gate expression to avoid stale local reuse MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The previous gate captured each subexpression in a named local (high_frequency, elapsed, woke). Locals are easy to reuse later in the function, and we have hit bugs from stale reuse before — most recently is_high_frequency being read again instead of re-checked. Inline the expression directly into do_component_phase so there is nothing tempting to reuse downstream. --- esphome/core/application.h | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/esphome/core/application.h b/esphome/core/application.h index 4a18714d0d..5baf570e62 100644 --- a/esphome/core/application.h +++ b/esphome/core/application.h @@ -637,10 +637,12 @@ inline void ESPHOME_ALWAYS_INLINE Application::loop() { // flag preserves it. wake_request_take() exchange-clears the flag; wakes // that arrive during Phase B re-set it and run Phase B again on the next // iteration. - const bool high_frequency = HighFrequencyLoopRequester::is_high_frequency(); - const uint32_t elapsed = now - this->last_loop_; - const bool woke = esphome::wake_request_take(); - const bool do_component_phase = high_frequency || woke || (elapsed >= this->loop_interval_); + // + // wake_request_take() must always be called first since it does an + // atomic exchange to clear the flag, and we want to run the component phase + // if either the flag was set or the scheduler requested a high-frequency loop. + const bool do_component_phase = esphome::wake_request_take() || HighFrequencyLoopRequester::is_high_frequency() || + (now - this->last_loop_ >= this->loop_interval_); if (do_component_phase) { ComponentPhaseGuard phase_guard{*this};