Skip to content

wake_loop Moved from Socket Component into Core

wake_loop_threadsafe() and related wake primitives have moved from the socket component into core. The require_wake_loop_threadsafe() opt-in is deprecated (now a no-op) — wake works unconditionally on all platforms.

This is a breaking change for external components in ESPHome 2026.4.0 and later.

Background

PR #15446: Move wake_loop out of socket component into core

The wake mechanism originally lived in the socket component because the first implementation used a UDP loopback socket. Since then, every platform has moved to nearly-free primitives (FreeRTOS task notifications, esp_schedule(), ARM __sev()), and the socket dependency was unnecessary complexity: 12 components needed to call require_wake_loop_threadsafe(), #ifdef USE_WAKE_LOOP_THREADSAFE guards were needed at every call site, and platforms without networking had silent degradation (up to ~16ms latency).

Now it just works — no opt-in, no defines, no guards.

Platform wake mechanisms

Platform Mechanism
ESP32 FreeRTOS task notifications (ISR-safe)
LibreTiny FreeRTOS task notifications
ESP8266 esp_schedule() (IRAM-safe)
RP2040 __sev() / __wfe() (ARM CPU instructions)
Host UDP loopback socket + select()

What's Changing

Removed defines

  • USE_WAKE_LOOP_THREADSAFE — no longer needed, wake is always available
  • USE_SOCKET_SELECT_SUPPORT — replaced by USE_HOST where needed

Deprecated Python function

socket.require_wake_loop_threadsafe() (Python codegen helper) is deprecated (warns, no-op). Remove calls to it.

No more #ifdef guards

// Before
#if defined(USE_SOCKET_SELECT_SUPPORT) && defined(USE_WAKE_LOOP_THREADSAFE)
App.wake_loop_threadsafe();
#endif

// After
App.wake_loop_threadsafe();

Socket dependency no longer needed for wake

Components no longer need to declare socket as a dependency just for wake functionality:

# Before
AUTO_LOAD = ["socket"]  # just for wake_loop

# After — remove if socket was only needed for wake
# AUTO_LOAD = []

Who This Affects

  1. External components calling socket.require_wake_loop_threadsafe() in Python codegen — remove the call
  2. External components using #ifdef USE_WAKE_LOOP_THREADSAFE — remove the guard
  3. External components with socket in AUTO_LOAD only for wake — remove it
  4. External components checking USE_SOCKET_SELECT_SUPPORT — use USE_HOST instead

Migration Guide

C++ — remove #ifdef guards

// Before
void some_background_thread() {
#if defined(USE_SOCKET_SELECT_SUPPORT) && defined(USE_WAKE_LOOP_THREADSAFE)
  App.wake_loop_threadsafe();
#endif
}

// After
void some_background_thread() {
  App.wake_loop_threadsafe();
}

Python codegen — remove opt-in call and socket AUTO_LOAD

# Before
from esphome.components import socket

AUTO_LOAD = ["socket"]

async def to_code(config):
    socket.require_wake_loop_threadsafe()
    # ... rest of codegen

# After — remove socket AUTO_LOAD and require call
async def to_code(config):
    # ... rest of codegen (no wake opt-in needed)

Timeline

  • ESPHome 2026.4.0 (April 2026): Wake moved to core, require_wake_loop_threadsafe() deprecated
  • USE_WAKE_LOOP_THREADSAFE and USE_SOCKET_SELECT_SUPPORT defines removed immediately

Finding Code That Needs Updates

# Find require_wake_loop_threadsafe calls
grep -rn 'require_wake_loop_threadsafe' your_component/

# Find #ifdef guards
grep -rn 'USE_WAKE_LOOP_THREADSAFE' your_component/

# Find USE_SOCKET_SELECT_SUPPORT
grep -rn 'USE_SOCKET_SELECT_SUPPORT' your_component/

Questions?

If you have questions about migrating your external component, please ask in:

Comments

Feel free to leave a comment here to discuss this post wth others. You can ask questions, share your experience, or suggest improvements. If you have a question about a specific feature or issue, please consider using the ESPHome Discord. Stick to English and follow ESPHome's code of conduct. These comments exist on a discussion on GitHub, so you can also comment there directly if you prefer.