1
0
mirror of https://github.com/esphome/esphome.git synced 2026-02-08 00:31:58 +00:00

[web_server] Fix ESP8266 watchdog panic by deferring actions to main loop (#13765)

This commit is contained in:
J. Nick Koston
2026-02-05 06:20:04 +01:00
committed by GitHub
parent a556824875
commit 25c0073b2d
2 changed files with 6 additions and 20 deletions

View File

@@ -721,11 +721,7 @@ void WebServer::handle_switch_request(AsyncWebServerRequest *request, const UrlM
} }
if (action != SWITCH_ACTION_NONE) { if (action != SWITCH_ACTION_NONE) {
#ifdef USE_ESP8266
execute_switch_action(obj, action);
#else
this->defer([obj, action]() { execute_switch_action(obj, action); }); this->defer([obj, action]() { execute_switch_action(obj, action); });
#endif
request->send(200); request->send(200);
} else { } else {
request->send(404); request->send(404);
@@ -1645,11 +1641,7 @@ void WebServer::handle_lock_request(AsyncWebServerRequest *request, const UrlMat
} }
if (action != LOCK_ACTION_NONE) { if (action != LOCK_ACTION_NONE) {
#ifdef USE_ESP8266
execute_lock_action(obj, action);
#else
this->defer([obj, action]() { execute_lock_action(obj, action); }); this->defer([obj, action]() { execute_lock_action(obj, action); });
#endif
request->send(200); request->send(200);
} else { } else {
request->send(404); request->send(404);
@@ -2015,19 +2007,14 @@ void WebServer::handle_infrared_request(AsyncWebServerRequest *request, const Ur
return; return;
} }
#ifdef USE_ESP8266
// ESP8266 is single-threaded, call directly
call.set_raw_timings_base64url(encoded);
call.perform();
#else
// Defer to main loop for thread safety. Move encoded string into lambda to ensure // Defer to main loop for thread safety. Move encoded string into lambda to ensure
// it outlives the call - set_raw_timings_base64url stores a pointer, so the string // it outlives the call - set_raw_timings_base64url stores a pointer, so the string
// must remain valid until perform() completes. // must remain valid until perform() completes.
// ESP8266 also needs this because ESPAsyncWebServer callbacks run in "sys" context.
this->defer([call, encoded = std::move(encoded)]() mutable { this->defer([call, encoded = std::move(encoded)]() mutable {
call.set_raw_timings_base64url(encoded); call.set_raw_timings_base64url(encoded);
call.perform(); call.perform();
}); });
#endif
request->send(200); request->send(200);
return; return;

View File

@@ -42,13 +42,12 @@ using ParamNameType = const __FlashStringHelper *;
using ParamNameType = const char *; using ParamNameType = const char *;
#endif #endif
// ESP8266 is single-threaded, so actions can execute directly in request context. // All platforms need to defer actions to main loop thread.
// Multi-core platforms need to defer to main loop thread for thread safety. // Multi-core platforms need this for thread safety.
#ifdef USE_ESP8266 // ESP8266 needs this because ESPAsyncWebServer callbacks run in "sys" context
#define DEFER_ACTION(capture, action) action // (SDK system context), not "cont" context (continuation/main loop). Calling
#else // yield() from sys context causes a panic in the Arduino core.
#define DEFER_ACTION(capture, action) this->defer([capture]() mutable { action; }) #define DEFER_ACTION(capture, action) this->defer([capture]() mutable { action; })
#endif
/// Result of matching a URL against an entity /// Result of matching a URL against an entity
struct EntityMatchResult { struct EntityMatchResult {