Skip to content

Move ESP-NOW bridge RX processing out of callbacks#2060

Open
robekl wants to merge 1 commit intomeshcore-dev:devfrom
robekl:fix-espnow-bridge-callback-handoff
Open

Move ESP-NOW bridge RX processing out of callbacks#2060
robekl wants to merge 1 commit intomeshcore-dev:devfrom
robekl:fix-espnow-bridge-callback-handoff

Conversation

@robekl
Copy link
Contributor

@robekl robekl commented Mar 17, 2026

Summary

This fixes the ESP-NOW bridge receive path so callback context no longer allocates mesh packets, mutates duplicate-tracking state, or touches the packet manager queues.

Problem

ESPNowBridge::recv_cb() currently calls into onDataRecv(), which fully parses incoming frames and then:

  • allocates mesh::Packet objects
  • calls _seen_packets.hasSeen()
  • queues inbound packets via _mgr->queueInbound()
  • frees packets on failure

That work runs from the ESP-NOW callback path, while the main dispatcher loop is simultaneously using the same PacketManager and duplicate tables. StaticPoolPacketManager is not synchronized; it mutates raw arrays and counters directly. So the bridge was crossing the packet ownership boundary from callback context and could race the main loop.

This is the exact class of issue previously identified in thread-safety review: heavy callback-side processing over shared queue state.

Fix

This PR changes the bridge RX flow to a bounded mailbox model:

  • the ESP-NOW callback now only validates basic size, copies the raw frame into a small fixed queue, and returns
  • a short critical section protects queue head/tail/count publication
  • ESPNowBridge::loop() now drains queued raw frames in normal main-loop context
  • decryption, checksum validation, Packet allocation, duplicate checking, and _mgr->queueInbound() all happen from the main loop instead of callback context
  • overflow is handled explicitly with drop accounting and debug logging

Why this fixes it

After this change, callback context never touches:

  • StaticPoolPacketManager
  • SimpleMeshTables
  • mesh packet allocation/free paths

Those shared ownership structures are back to being single-context for this bridge implementation, which removes the queue corruption / duplicate-table race that existed before.

Validation

Built successfully:

  • Heltec_v2_repeater_bridge_espnow

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant