From 617178c791f80511bc458c2027113bd296118e13 Mon Sep 17 00:00:00 2001 From: Paul Guyot Date: Tue, 14 Jul 2026 03:53:50 +0200 Subject: [PATCH] esp32: return from receive_events once drained Fix ESP32 event poller re-blocking after running a listener, which could delay a process readied by a driver (e.g. an active-mode socket message) until the next event or timer tick Signed-off-by: Paul Guyot --- CHANGELOG.md | 2 ++ src/platforms/esp32/components/avm_sys/sys.c | 3 +++ 2 files changed, 5 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8bb52ca3e6..57d8268efb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -70,6 +70,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Fixed several underallocation issues that could trigger data corruption on `binary:replace`, `zlib:compress` and bsd socket recv code. - Fixed a bug where `catch` would raise on regular atom results - Fixed ESP32 socket driver holding the global socket-list lock across blocking TCP connects, leaking the port on connect failure, losing concurrent `accept` waiters, leaking `netbuf` on receive error paths, and a recycled-`netconn` race between socket close and the event handler +- Fixed the ESP32 event poller re-blocking after running a listener, which could delay a process + readied by a driver (e.g. an active-mode socket message) until the next event or timer tick ## [0.7.0-alpha.1] - 2026-04-06 diff --git a/src/platforms/esp32/components/avm_sys/sys.c b/src/platforms/esp32/components/avm_sys/sys.c index 42786b6c8e..10909d9750 100644 --- a/src/platforms/esp32/components/avm_sys/sys.c +++ b/src/platforms/esp32/components/avm_sys/sys.c @@ -132,6 +132,9 @@ static void receive_events(GlobalContext *glb, TickType_t wait_ticks) void *sender = NULL; QueueSetMemberHandle_t event_source; while ((event_source = xQueueSelectFromSet(event_set, wait_ticks))) { + // Drain without re-blocking after the first event, then return so the + // scheduler loop can run any process a listener just made ready + wait_ticks = 0; // Listener used shared event_queue. if (event_source == event_queue) { if (UNLIKELY(xQueueReceive(event_queue, &sender, 0) == pdFALSE)) {